@alleyboss/micropay-solana-x402-paywall 2.3.0 → 3.0.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.
Files changed (70) hide show
  1. package/README.md +72 -116
  2. package/dist/agent/index.cjs +358 -0
  3. package/dist/agent/index.cjs.map +1 -0
  4. package/dist/agent/index.d.cts +221 -0
  5. package/dist/agent/index.d.ts +221 -0
  6. package/dist/agent/index.js +347 -0
  7. package/dist/agent/index.js.map +1 -0
  8. package/dist/client/index.cjs +1 -1
  9. package/dist/client/index.cjs.map +1 -1
  10. package/dist/client/index.d.cts +10 -1
  11. package/dist/client/index.d.ts +10 -1
  12. package/dist/client/index.js +1 -1
  13. package/dist/client/index.js.map +1 -1
  14. package/dist/express/index.cjs +79 -0
  15. package/dist/express/index.cjs.map +1 -0
  16. package/dist/express/index.d.cts +40 -0
  17. package/dist/express/index.d.ts +40 -0
  18. package/dist/express/index.js +76 -0
  19. package/dist/express/index.js.map +1 -0
  20. package/dist/index.cjs +315 -1116
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +6 -10
  23. package/dist/index.d.ts +6 -10
  24. package/dist/index.js +283 -1074
  25. package/dist/index.js.map +1 -1
  26. package/dist/session/index.cjs.map +1 -1
  27. package/dist/session/index.d.cts +1 -1
  28. package/dist/session/index.d.ts +1 -1
  29. package/dist/session/index.js.map +1 -1
  30. package/dist/{session-D2IoWAWV.d.cts → types-BWYQMw03.d.cts} +1 -16
  31. package/dist/{session-D2IoWAWV.d.ts → types-BWYQMw03.d.ts} +1 -16
  32. package/package.json +29 -59
  33. package/dist/client-D-dteoJw.d.cts +0 -63
  34. package/dist/client-DfCIRrNG.d.ts +0 -63
  35. package/dist/memory-Daxkczti.d.cts +0 -29
  36. package/dist/memory-Daxkczti.d.ts +0 -29
  37. package/dist/middleware/index.cjs +0 -273
  38. package/dist/middleware/index.cjs.map +0 -1
  39. package/dist/middleware/index.d.cts +0 -91
  40. package/dist/middleware/index.d.ts +0 -91
  41. package/dist/middleware/index.js +0 -267
  42. package/dist/middleware/index.js.map +0 -1
  43. package/dist/nextjs-BDyOqGAq.d.cts +0 -81
  44. package/dist/nextjs-CbX8_9yK.d.ts +0 -81
  45. package/dist/payment-BGp7eMQl.d.cts +0 -103
  46. package/dist/payment-BGp7eMQl.d.ts +0 -103
  47. package/dist/solana/index.cjs +0 -589
  48. package/dist/solana/index.cjs.map +0 -1
  49. package/dist/solana/index.d.cts +0 -240
  50. package/dist/solana/index.d.ts +0 -240
  51. package/dist/solana/index.js +0 -567
  52. package/dist/solana/index.js.map +0 -1
  53. package/dist/store/index.cjs +0 -99
  54. package/dist/store/index.cjs.map +0 -1
  55. package/dist/store/index.d.cts +0 -38
  56. package/dist/store/index.d.ts +0 -38
  57. package/dist/store/index.js +0 -96
  58. package/dist/store/index.js.map +0 -1
  59. package/dist/utils/index.cjs +0 -68
  60. package/dist/utils/index.cjs.map +0 -1
  61. package/dist/utils/index.d.cts +0 -30
  62. package/dist/utils/index.d.ts +0 -30
  63. package/dist/utils/index.js +0 -65
  64. package/dist/utils/index.js.map +0 -1
  65. package/dist/x402/index.cjs +0 -387
  66. package/dist/x402/index.cjs.map +0 -1
  67. package/dist/x402/index.d.cts +0 -96
  68. package/dist/x402/index.d.ts +0 -96
  69. package/dist/x402/index.js +0 -375
  70. package/dist/x402/index.js.map +0 -1
@@ -1,103 +0,0 @@
1
- /** x402 network identifiers for Solana */
2
- type X402Network = 'solana-devnet' | 'solana-mainnet';
3
- /** Solana network types */
4
- type SolanaNetwork = 'devnet' | 'mainnet-beta';
5
- /** SPL Token asset specification */
6
- interface SPLTokenAsset {
7
- /** Token mint address */
8
- mint: string;
9
- /** Token decimals (default: 6 for USDC/USDT) */
10
- decimals?: number;
11
- }
12
- /** Asset types for payments */
13
- type PaymentAsset = 'native' | 'usdc' | 'usdt' | SPLTokenAsset;
14
- /** Known SPL token mint addresses */
15
- declare const TOKEN_MINTS: {
16
- /** USDC on mainnet */
17
- readonly USDC_MAINNET: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
18
- /** USDC on devnet */
19
- readonly USDC_DEVNET: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU";
20
- /** USDT on mainnet */
21
- readonly USDT_MAINNET: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB";
22
- };
23
- /** Payment requirement for x402 protocol */
24
- interface PaymentRequirement {
25
- /** Payment scheme - currently only 'exact' is supported */
26
- scheme: 'exact';
27
- /** Network identifier for x402 */
28
- network: X402Network;
29
- /** Amount in smallest unit as string (lamports for SOL, base units for tokens) */
30
- maxAmountRequired: string;
31
- /** URL of the protected resource */
32
- resource: string;
33
- /** Human-readable description */
34
- description: string;
35
- /** MIME type of the resource */
36
- mimeType?: string;
37
- /** Recipient wallet address */
38
- payTo: string;
39
- /** Maximum time in seconds to complete payment */
40
- maxTimeoutSeconds: number;
41
- /** Asset type - 'native' for SOL, 'usdc', 'usdt', or custom mint */
42
- asset: PaymentAsset;
43
- /** Additional metadata */
44
- extra?: {
45
- name?: string;
46
- articleId?: string;
47
- [key: string]: unknown;
48
- };
49
- }
50
- /** Payment payload sent by client after transaction */
51
- interface PaymentPayload {
52
- /** x402 protocol version */
53
- x402Version: number;
54
- /** Payment scheme */
55
- scheme: 'exact';
56
- /** Network identifier */
57
- network: X402Network;
58
- /** Transaction details */
59
- payload: {
60
- /** Transaction signature (base58) */
61
- signature: string;
62
- /** Base64 encoded transaction (optional) */
63
- transaction?: string;
64
- };
65
- }
66
- /** Request to verify a payment */
67
- interface VerificationRequest {
68
- paymentPayload: PaymentPayload;
69
- paymentRequirements: PaymentRequirement;
70
- }
71
- /** Response from payment verification */
72
- interface VerificationResponse {
73
- /** Whether the payment is valid */
74
- valid: boolean;
75
- /** Reason for invalid payment */
76
- invalidReason?: string;
77
- /** Whether the transaction is settled on-chain */
78
- settled?: boolean;
79
- /** Sender wallet address (payer) */
80
- from?: string;
81
- /** Transaction details */
82
- transaction?: {
83
- signature: string;
84
- blockTime?: number;
85
- slot?: number;
86
- };
87
- }
88
- /** Payment status for tracking */
89
- interface PaymentStatus {
90
- status: 'pending' | 'confirmed' | 'failed' | 'expired';
91
- signature?: string;
92
- confirmations?: number;
93
- error?: string;
94
- }
95
- /** Configuration for article pricing */
96
- interface ArticlePaymentConfig {
97
- articleId: string;
98
- priceInLamports: bigint;
99
- title: string;
100
- description?: string;
101
- }
102
-
103
- export { type ArticlePaymentConfig as A, type PaymentRequirement as P, type SolanaNetwork as S, TOKEN_MINTS as T, type VerificationRequest as V, type X402Network as X, type PaymentPayload as a, type VerificationResponse as b, type PaymentStatus as c, type PaymentAsset as d, type SPLTokenAsset as e };
@@ -1,589 +0,0 @@
1
- 'use strict';
2
-
3
- var web3_js = require('@solana/web3.js');
4
-
5
- // src/solana/client.ts
6
- var cachedConnection = null;
7
- var cachedNetwork = null;
8
- var cachedFallbacks = [];
9
- var cachedFallbackEnabled = false;
10
- function buildRpcUrl(config) {
11
- const { network, rpcUrl, tatumApiKey } = config;
12
- if (rpcUrl) {
13
- if (rpcUrl.includes("tatum.io") && tatumApiKey && !rpcUrl.includes(tatumApiKey)) {
14
- return rpcUrl.endsWith("/") ? `${rpcUrl}${tatumApiKey}` : `${rpcUrl}/${tatumApiKey}`;
15
- }
16
- return rpcUrl;
17
- }
18
- if (tatumApiKey) {
19
- const baseUrl = network === "mainnet-beta" ? "https://solana-mainnet.gateway.tatum.io" : "https://solana-devnet.gateway.tatum.io";
20
- return `${baseUrl}/${tatumApiKey}`;
21
- }
22
- return web3_js.clusterApiUrl(network);
23
- }
24
- function createConnection(rpcUrl) {
25
- return new web3_js.Connection(rpcUrl, {
26
- commitment: "confirmed",
27
- confirmTransactionInitialTimeout: 6e4
28
- });
29
- }
30
- function getConnection(config) {
31
- const { network } = config;
32
- if (cachedConnection && cachedNetwork === network) {
33
- return cachedConnection;
34
- }
35
- const rpcUrl = buildRpcUrl(config);
36
- cachedConnection = createConnection(rpcUrl);
37
- cachedNetwork = network;
38
- cachedFallbackEnabled = config.enableFallback ?? false;
39
- cachedFallbacks = [];
40
- if (cachedFallbackEnabled && config.fallbackRpcUrls?.length) {
41
- cachedFallbacks = config.fallbackRpcUrls.map(createConnection);
42
- }
43
- return cachedConnection;
44
- }
45
- function getConnectionWithFallback(config) {
46
- const connection = getConnection(config);
47
- return {
48
- connection,
49
- fallbacks: cachedFallbacks,
50
- fallbackEnabled: cachedFallbackEnabled
51
- };
52
- }
53
- async function withFallback(config, operation) {
54
- const { connection, fallbacks, fallbackEnabled } = getConnectionWithFallback(config);
55
- try {
56
- return await operation(connection);
57
- } catch (error) {
58
- if (!fallbackEnabled || fallbacks.length === 0) {
59
- throw error;
60
- }
61
- if (!isRetryableError(error)) {
62
- throw error;
63
- }
64
- for (let i = 0; i < fallbacks.length; i++) {
65
- try {
66
- return await operation(fallbacks[i]);
67
- } catch (fallbackError) {
68
- if (i === fallbacks.length - 1) {
69
- throw fallbackError;
70
- }
71
- }
72
- }
73
- throw error;
74
- }
75
- }
76
- function isRetryableError(error) {
77
- if (error instanceof Error) {
78
- const message = error.message.toLowerCase();
79
- return message.includes("429") || message.includes("503") || message.includes("502") || message.includes("timeout") || message.includes("econnrefused") || message.includes("enotfound") || message.includes("rate limit");
80
- }
81
- return false;
82
- }
83
- function resetConnection() {
84
- cachedConnection = null;
85
- cachedNetwork = null;
86
- }
87
- function isMainnet(network) {
88
- return network === "mainnet-beta";
89
- }
90
- function toX402Network(network) {
91
- return network === "mainnet-beta" ? "solana-mainnet" : "solana-devnet";
92
- }
93
- var SIGNATURE_REGEX = /^[1-9A-HJ-NP-Za-km-z]{87,88}$/;
94
- var WALLET_REGEX = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
95
- function isValidSignature(signature) {
96
- if (!signature || typeof signature !== "string") return false;
97
- return SIGNATURE_REGEX.test(signature);
98
- }
99
- function isValidWalletAddress(address) {
100
- if (!address || typeof address !== "string") return false;
101
- return WALLET_REGEX.test(address);
102
- }
103
- function parseSOLTransfer(transaction, expectedRecipient) {
104
- const instructions = transaction.transaction.message.instructions;
105
- for (const ix of instructions) {
106
- if ("parsed" in ix && ix.program === "system") {
107
- const parsed = ix.parsed;
108
- if (parsed.type === "transfer" && parsed.info.destination === expectedRecipient) {
109
- return {
110
- from: parsed.info.source,
111
- to: parsed.info.destination,
112
- amount: BigInt(parsed.info.lamports)
113
- };
114
- }
115
- }
116
- }
117
- if (transaction.meta?.innerInstructions) {
118
- for (const inner of transaction.meta.innerInstructions) {
119
- for (const ix of inner.instructions) {
120
- if ("parsed" in ix && ix.program === "system") {
121
- const parsed = ix.parsed;
122
- if (parsed.type === "transfer" && parsed.info.destination === expectedRecipient) {
123
- return {
124
- from: parsed.info.source,
125
- to: parsed.info.destination,
126
- amount: BigInt(parsed.info.lamports)
127
- };
128
- }
129
- }
130
- }
131
- }
132
- }
133
- return null;
134
- }
135
- async function verifyPayment(params) {
136
- const {
137
- signature,
138
- expectedRecipient,
139
- expectedAmount,
140
- maxAgeSeconds = 300,
141
- clientConfig,
142
- signatureStore
143
- } = params;
144
- if (!isValidSignature(signature)) {
145
- return { valid: false, confirmed: false, signature, error: "Invalid signature format" };
146
- }
147
- if (!isValidWalletAddress(expectedRecipient)) {
148
- return { valid: false, confirmed: false, signature, error: "Invalid recipient address" };
149
- }
150
- if (expectedAmount <= 0n) {
151
- return { valid: false, confirmed: false, signature, error: "Invalid expected amount" };
152
- }
153
- if (signatureStore) {
154
- const isUsed = await signatureStore.hasBeenUsed(signature);
155
- if (isUsed) {
156
- return { valid: false, confirmed: true, signature, error: "Signature already used" };
157
- }
158
- }
159
- const effectiveMaxAge = Math.min(Math.max(maxAgeSeconds, 60), 3600);
160
- const connection = getConnection(clientConfig);
161
- try {
162
- const transaction = await connection.getParsedTransaction(signature, {
163
- commitment: "confirmed",
164
- maxSupportedTransactionVersion: 0
165
- });
166
- if (!transaction) {
167
- return { valid: false, confirmed: false, signature, error: "Transaction not found" };
168
- }
169
- if (transaction.meta?.err) {
170
- return {
171
- valid: false,
172
- confirmed: true,
173
- signature,
174
- error: "Transaction failed on-chain"
175
- };
176
- }
177
- if (transaction.blockTime) {
178
- const now = Math.floor(Date.now() / 1e3);
179
- if (now - transaction.blockTime > effectiveMaxAge) {
180
- return { valid: false, confirmed: true, signature, error: "Transaction too old" };
181
- }
182
- if (transaction.blockTime > now + 60) {
183
- return { valid: false, confirmed: true, signature, error: "Invalid transaction time" };
184
- }
185
- }
186
- const transferDetails = parseSOLTransfer(transaction, expectedRecipient);
187
- if (!transferDetails) {
188
- return {
189
- valid: false,
190
- confirmed: true,
191
- signature,
192
- error: "No valid SOL transfer to recipient found"
193
- };
194
- }
195
- if (transferDetails.amount < expectedAmount) {
196
- return {
197
- valid: false,
198
- confirmed: true,
199
- signature,
200
- from: transferDetails.from,
201
- to: transferDetails.to,
202
- amount: transferDetails.amount,
203
- error: "Insufficient payment amount"
204
- };
205
- }
206
- return {
207
- valid: true,
208
- confirmed: true,
209
- signature,
210
- from: transferDetails.from,
211
- to: transferDetails.to,
212
- amount: transferDetails.amount,
213
- blockTime: transaction.blockTime ?? void 0,
214
- slot: transaction.slot
215
- };
216
- } catch (error) {
217
- return {
218
- valid: false,
219
- confirmed: false,
220
- signature,
221
- error: "Verification failed"
222
- };
223
- }
224
- }
225
- async function waitForConfirmation(signature, clientConfig) {
226
- if (!isValidSignature(signature)) {
227
- return { confirmed: false, error: "Invalid signature format" };
228
- }
229
- const connection = getConnection(clientConfig);
230
- try {
231
- const confirmation = await connection.confirmTransaction(signature, "confirmed");
232
- if (confirmation.value.err) {
233
- return { confirmed: false, error: "Transaction failed" };
234
- }
235
- return { confirmed: true, slot: confirmation.context?.slot };
236
- } catch {
237
- return { confirmed: false, error: "Confirmation timeout" };
238
- }
239
- }
240
- async function getWalletTransactions(walletAddress, clientConfig, limit = 20) {
241
- if (!isValidWalletAddress(walletAddress)) {
242
- return [];
243
- }
244
- const safeLimit = Math.min(Math.max(limit, 1), 100);
245
- const connection = getConnection(clientConfig);
246
- try {
247
- const pubkey = new web3_js.PublicKey(walletAddress);
248
- const signatures = await connection.getSignaturesForAddress(pubkey, { limit: safeLimit });
249
- return signatures.map((sig) => ({
250
- signature: sig.signature,
251
- blockTime: sig.blockTime ?? void 0,
252
- slot: sig.slot
253
- }));
254
- } catch {
255
- return [];
256
- }
257
- }
258
- function lamportsToSol(lamports) {
259
- return Number(lamports) / web3_js.LAMPORTS_PER_SOL;
260
- }
261
- function solToLamports(sol) {
262
- if (!Number.isFinite(sol) || sol < 0) {
263
- throw new Error("Invalid SOL amount");
264
- }
265
- return BigInt(Math.floor(sol * web3_js.LAMPORTS_PER_SOL));
266
- }
267
-
268
- // src/types/payment.ts
269
- var TOKEN_MINTS = {
270
- /** USDC on mainnet */
271
- USDC_MAINNET: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
272
- /** USDC on devnet */
273
- USDC_DEVNET: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
274
- /** USDT on mainnet */
275
- USDT_MAINNET: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB"
276
- };
277
-
278
- // src/solana/spl.ts
279
- var SIGNATURE_REGEX2 = /^[1-9A-HJ-NP-Za-km-z]{87,88}$/;
280
- var WALLET_REGEX2 = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
281
- function resolveMintAddress(asset, network) {
282
- if (asset === "native") return null;
283
- if (asset === "usdc") {
284
- return network === "mainnet-beta" ? TOKEN_MINTS.USDC_MAINNET : TOKEN_MINTS.USDC_DEVNET;
285
- }
286
- if (asset === "usdt") {
287
- return TOKEN_MINTS.USDT_MAINNET;
288
- }
289
- if (typeof asset === "object" && "mint" in asset) {
290
- return asset.mint;
291
- }
292
- return null;
293
- }
294
- function getTokenDecimals(asset) {
295
- if (asset === "native") return 9;
296
- if (asset === "usdc" || asset === "usdt") return 6;
297
- if (typeof asset === "object" && "decimals" in asset) {
298
- return asset.decimals ?? 6;
299
- }
300
- return 6;
301
- }
302
- function parseSPLTransfer(transaction, expectedRecipient, expectedMint) {
303
- const instructions = transaction.transaction.message.instructions;
304
- for (const ix of instructions) {
305
- if ("parsed" in ix && (ix.program === "spl-token" || ix.program === "spl-token-2022")) {
306
- const parsed = ix.parsed;
307
- if (parsed.type === "transfer" || parsed.type === "transferChecked") {
308
- const amount = parsed.info.amount || parsed.info.tokenAmount?.amount;
309
- if (amount && parsed.info.destination) {
310
- return {
311
- from: parsed.info.authority || parsed.info.source || "",
312
- to: parsed.info.destination,
313
- amount: BigInt(amount),
314
- mint: parsed.info.mint || expectedMint
315
- };
316
- }
317
- }
318
- }
319
- }
320
- if (transaction.meta?.innerInstructions) {
321
- for (const inner of transaction.meta.innerInstructions) {
322
- for (const ix of inner.instructions) {
323
- if ("parsed" in ix && (ix.program === "spl-token" || ix.program === "spl-token-2022")) {
324
- const parsed = ix.parsed;
325
- if (parsed.type === "transfer" || parsed.type === "transferChecked") {
326
- const amount = parsed.info.amount || parsed.info.tokenAmount?.amount;
327
- if (amount) {
328
- return {
329
- from: parsed.info.authority || parsed.info.source || "",
330
- to: parsed.info.destination || "",
331
- amount: BigInt(amount),
332
- mint: parsed.info.mint || expectedMint
333
- };
334
- }
335
- }
336
- }
337
- }
338
- }
339
- }
340
- if (transaction.meta?.postTokenBalances && transaction.meta?.preTokenBalances) {
341
- const preBalances = transaction.meta.preTokenBalances;
342
- const postBalances = transaction.meta.postTokenBalances;
343
- for (const post of postBalances) {
344
- if (post.mint === expectedMint && post.owner === expectedRecipient) {
345
- const pre = preBalances.find(
346
- (p) => p.accountIndex === post.accountIndex
347
- );
348
- const preAmount = BigInt(pre?.uiTokenAmount?.amount || "0");
349
- const postAmount = BigInt(post.uiTokenAmount?.amount || "0");
350
- const transferred = postAmount - preAmount;
351
- if (transferred > 0n) {
352
- return {
353
- from: "",
354
- // Can't determine from balance changes
355
- to: expectedRecipient,
356
- amount: transferred,
357
- mint: expectedMint
358
- };
359
- }
360
- }
361
- }
362
- }
363
- return null;
364
- }
365
- async function verifySPLPayment(params) {
366
- const {
367
- signature,
368
- expectedRecipient,
369
- expectedAmount,
370
- asset,
371
- clientConfig,
372
- maxAgeSeconds = 300,
373
- signatureStore
374
- } = params;
375
- if (signatureStore) {
376
- const isUsed = await signatureStore.hasBeenUsed(signature);
377
- if (isUsed) {
378
- return { valid: false, confirmed: true, signature, error: "Signature already used" };
379
- }
380
- }
381
- if (!SIGNATURE_REGEX2.test(signature)) {
382
- return { valid: false, confirmed: false, signature, error: "Invalid signature format" };
383
- }
384
- if (!WALLET_REGEX2.test(expectedRecipient)) {
385
- return { valid: false, confirmed: false, signature, error: "Invalid recipient address" };
386
- }
387
- const mintAddress = resolveMintAddress(asset, clientConfig.network);
388
- if (!mintAddress) {
389
- return { valid: false, confirmed: false, signature, error: "Invalid asset configuration" };
390
- }
391
- if (expectedAmount <= 0n) {
392
- return { valid: false, confirmed: false, signature, error: "Invalid expected amount" };
393
- }
394
- const effectiveMaxAge = Math.min(Math.max(maxAgeSeconds, 60), 3600);
395
- const connection = getConnection(clientConfig);
396
- try {
397
- const transaction = await connection.getParsedTransaction(signature, {
398
- commitment: "confirmed",
399
- maxSupportedTransactionVersion: 0
400
- });
401
- if (!transaction) {
402
- return { valid: false, confirmed: false, signature, error: "Transaction not found" };
403
- }
404
- if (transaction.meta?.err) {
405
- return { valid: false, confirmed: true, signature, error: "Transaction failed on-chain" };
406
- }
407
- if (transaction.blockTime) {
408
- const now = Math.floor(Date.now() / 1e3);
409
- if (now - transaction.blockTime > effectiveMaxAge) {
410
- return { valid: false, confirmed: true, signature, error: "Transaction too old" };
411
- }
412
- if (transaction.blockTime > now + 60) {
413
- return { valid: false, confirmed: true, signature, error: "Invalid transaction time" };
414
- }
415
- }
416
- const transfer = parseSPLTransfer(transaction, expectedRecipient, mintAddress);
417
- if (!transfer) {
418
- return {
419
- valid: false,
420
- confirmed: true,
421
- signature,
422
- error: "No valid token transfer to recipient found"
423
- };
424
- }
425
- if (transfer.to) {
426
- try {
427
- const destinationInfo = await connection.getParsedAccountInfo(new web3_js.PublicKey(transfer.to));
428
- const owner = destinationInfo.value?.data?.parsed?.info?.owner;
429
- if (owner && owner !== expectedRecipient) {
430
- return {
431
- valid: false,
432
- confirmed: true,
433
- signature,
434
- error: "Recipient mismatch: Token account not owned by merchant"
435
- };
436
- }
437
- } catch (e) {
438
- return {
439
- valid: false,
440
- confirmed: true,
441
- signature,
442
- error: "Could not verify token account owner"
443
- };
444
- }
445
- }
446
- if (transfer.mint !== mintAddress) {
447
- return {
448
- valid: false,
449
- confirmed: true,
450
- signature,
451
- error: "Token mint mismatch"
452
- };
453
- }
454
- if (transfer.amount < expectedAmount) {
455
- return {
456
- valid: false,
457
- confirmed: true,
458
- signature,
459
- from: transfer.from,
460
- to: transfer.to,
461
- mint: transfer.mint,
462
- amount: transfer.amount,
463
- error: "Insufficient payment amount"
464
- };
465
- }
466
- return {
467
- valid: true,
468
- confirmed: true,
469
- signature,
470
- from: transfer.from,
471
- to: transfer.to,
472
- mint: transfer.mint,
473
- amount: transfer.amount,
474
- blockTime: transaction.blockTime ?? void 0,
475
- slot: transaction.slot
476
- };
477
- } catch {
478
- return { valid: false, confirmed: false, signature, error: "Verification failed" };
479
- }
480
- }
481
- function isNativeAsset(asset) {
482
- return asset === "native";
483
- }
484
- var DEFAULT_COMPUTE_UNITS = 2e5;
485
- var DEFAULT_MICRO_LAMPORTS = 1e3;
486
- function createPriorityFeeInstructions(config = {}) {
487
- const { enabled = false, microLamports, computeUnits } = config;
488
- if (!enabled) {
489
- return [];
490
- }
491
- const instructions = [];
492
- const units = computeUnits ?? DEFAULT_COMPUTE_UNITS;
493
- instructions.push(web3_js.ComputeBudgetProgram.setComputeUnitLimit({ units }));
494
- const price = microLamports ?? DEFAULT_MICRO_LAMPORTS;
495
- instructions.push(web3_js.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: price }));
496
- return instructions;
497
- }
498
- async function estimatePriorityFee(connection, accounts = []) {
499
- try {
500
- const fees = await connection.getRecentPrioritizationFees({
501
- lockedWritableAccounts: accounts
502
- });
503
- if (fees.length === 0) {
504
- return DEFAULT_MICRO_LAMPORTS;
505
- }
506
- const sortedFees = fees.map((f) => f.prioritizationFee).filter((f) => f > 0).sort((a, b) => a - b);
507
- if (sortedFees.length === 0) {
508
- return DEFAULT_MICRO_LAMPORTS;
509
- }
510
- const medianIndex = Math.floor(sortedFees.length / 2);
511
- return sortedFees[medianIndex];
512
- } catch {
513
- return DEFAULT_MICRO_LAMPORTS;
514
- }
515
- }
516
- function calculatePriorityFeeCost(microLamportsPerCU, computeUnits) {
517
- return Math.ceil(microLamportsPerCU * computeUnits / 1e6);
518
- }
519
- async function buildVersionedTransaction(config) {
520
- const {
521
- connection,
522
- payer,
523
- instructions,
524
- lookupTables = [],
525
- priorityFee,
526
- recentBlockhash
527
- } = config;
528
- const priorityIxs = createPriorityFeeInstructions(priorityFee);
529
- const allInstructions = [...priorityIxs, ...instructions];
530
- let blockhash;
531
- let lastValidBlockHeight;
532
- if (recentBlockhash) {
533
- blockhash = recentBlockhash;
534
- const slot = await connection.getSlot();
535
- lastValidBlockHeight = slot + 150;
536
- } else {
537
- const latestBlockhash = await connection.getLatestBlockhash("confirmed");
538
- blockhash = latestBlockhash.blockhash;
539
- lastValidBlockHeight = latestBlockhash.lastValidBlockHeight;
540
- }
541
- const message = new web3_js.TransactionMessage({
542
- payerKey: payer,
543
- recentBlockhash: blockhash,
544
- instructions: allInstructions
545
- }).compileToV0Message(lookupTables);
546
- const transaction = new web3_js.VersionedTransaction(message);
547
- return {
548
- transaction,
549
- blockhash,
550
- lastValidBlockHeight
551
- };
552
- }
553
- async function fetchLookupTables(connection, addresses) {
554
- const tables = [];
555
- for (const address of addresses) {
556
- const result = await connection.getAddressLookupTable(address);
557
- if (result.value) {
558
- tables.push(result.value);
559
- }
560
- }
561
- return tables;
562
- }
563
- function isVersionedTransaction(tx) {
564
- return tx instanceof web3_js.VersionedTransaction;
565
- }
566
-
567
- exports.buildVersionedTransaction = buildVersionedTransaction;
568
- exports.calculatePriorityFeeCost = calculatePriorityFeeCost;
569
- exports.createPriorityFeeInstructions = createPriorityFeeInstructions;
570
- exports.estimatePriorityFee = estimatePriorityFee;
571
- exports.fetchLookupTables = fetchLookupTables;
572
- exports.getConnection = getConnection;
573
- exports.getConnectionWithFallback = getConnectionWithFallback;
574
- exports.getTokenDecimals = getTokenDecimals;
575
- exports.getWalletTransactions = getWalletTransactions;
576
- exports.isMainnet = isMainnet;
577
- exports.isNativeAsset = isNativeAsset;
578
- exports.isVersionedTransaction = isVersionedTransaction;
579
- exports.lamportsToSol = lamportsToSol;
580
- exports.resetConnection = resetConnection;
581
- exports.resolveMintAddress = resolveMintAddress;
582
- exports.solToLamports = solToLamports;
583
- exports.toX402Network = toX402Network;
584
- exports.verifyPayment = verifyPayment;
585
- exports.verifySPLPayment = verifySPLPayment;
586
- exports.waitForConfirmation = waitForConfirmation;
587
- exports.withFallback = withFallback;
588
- //# sourceMappingURL=index.cjs.map
589
- //# sourceMappingURL=index.cjs.map