@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
@@ -0,0 +1,347 @@
1
+ import { PublicKey, SystemProgram, LAMPORTS_PER_SOL, Keypair, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } from '@solana/web3.js';
2
+ import { SignJWT, jwtVerify } from 'jose';
3
+ import { v4 } from 'uuid';
4
+
5
+ // src/agent/agentPayment.ts
6
+ var DEFAULT_COMPUTE_UNITS = 2e5;
7
+ var DEFAULT_MICRO_LAMPORTS = 1e3;
8
+ function createPriorityFeeInstructions(config = {}) {
9
+ const { enabled = false, microLamports, computeUnits } = config;
10
+ if (!enabled) {
11
+ return [];
12
+ }
13
+ const instructions = [];
14
+ const units = computeUnits ?? DEFAULT_COMPUTE_UNITS;
15
+ instructions.push(ComputeBudgetProgram.setComputeUnitLimit({ units }));
16
+ const price = microLamports ?? DEFAULT_MICRO_LAMPORTS;
17
+ instructions.push(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: price }));
18
+ return instructions;
19
+ }
20
+ async function buildVersionedTransaction(config) {
21
+ const {
22
+ connection,
23
+ payer,
24
+ instructions,
25
+ priorityFee,
26
+ recentBlockhash
27
+ } = config;
28
+ const priorityIxs = createPriorityFeeInstructions(priorityFee);
29
+ const allInstructions = [...priorityIxs, ...instructions];
30
+ let blockhash;
31
+ let lastValidBlockHeight;
32
+ if (recentBlockhash) {
33
+ blockhash = recentBlockhash;
34
+ const slot = await connection.getSlot();
35
+ lastValidBlockHeight = slot + 150;
36
+ } else {
37
+ const latestBlockhash = await connection.getLatestBlockhash("confirmed");
38
+ blockhash = latestBlockhash.blockhash;
39
+ lastValidBlockHeight = latestBlockhash.lastValidBlockHeight;
40
+ }
41
+ const message = new TransactionMessage({
42
+ payerKey: payer,
43
+ recentBlockhash: blockhash,
44
+ instructions: allInstructions
45
+ }).compileToV0Message([]);
46
+ const transaction = new VersionedTransaction(message);
47
+ return {
48
+ transaction,
49
+ blockhash,
50
+ lastValidBlockHeight
51
+ };
52
+ }
53
+
54
+ // src/agent/agentPayment.ts
55
+ var WALLET_REGEX = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
56
+ function isValidWalletAddress(address) {
57
+ if (!address || typeof address !== "string") return false;
58
+ return WALLET_REGEX.test(address);
59
+ }
60
+ async function executeAgentPayment(params) {
61
+ const {
62
+ connection,
63
+ agentKeypair,
64
+ recipientAddress,
65
+ amountLamports,
66
+ priorityFee,
67
+ confirmationTimeout = 6e4
68
+ } = params;
69
+ if (!isValidWalletAddress(recipientAddress)) {
70
+ return {
71
+ success: false,
72
+ error: "Invalid recipient address format"
73
+ };
74
+ }
75
+ if (amountLamports <= 0n) {
76
+ return {
77
+ success: false,
78
+ error: "Amount must be greater than 0"
79
+ };
80
+ }
81
+ try {
82
+ const recipientPubkey = new PublicKey(recipientAddress);
83
+ const transferInstruction = SystemProgram.transfer({
84
+ fromPubkey: agentKeypair.publicKey,
85
+ toPubkey: recipientPubkey,
86
+ lamports: amountLamports
87
+ });
88
+ const { transaction, lastValidBlockHeight } = await buildVersionedTransaction({
89
+ connection,
90
+ payer: agentKeypair.publicKey,
91
+ instructions: [transferInstruction],
92
+ priorityFee
93
+ });
94
+ transaction.sign([agentKeypair]);
95
+ const signature = await connection.sendTransaction(transaction, {
96
+ maxRetries: 3,
97
+ skipPreflight: false
98
+ });
99
+ const confirmationPromise = connection.confirmTransaction(
100
+ {
101
+ signature,
102
+ lastValidBlockHeight,
103
+ blockhash: transaction.message.recentBlockhash
104
+ },
105
+ "confirmed"
106
+ );
107
+ const timeoutPromise = new Promise((_, reject) => {
108
+ setTimeout(() => reject(new Error("Confirmation timeout")), confirmationTimeout);
109
+ });
110
+ const confirmation = await Promise.race([confirmationPromise, timeoutPromise]);
111
+ if (confirmation.value.err) {
112
+ return {
113
+ success: false,
114
+ signature,
115
+ error: "Transaction failed on-chain"
116
+ };
117
+ }
118
+ const txDetails = await connection.getTransaction(signature, {
119
+ commitment: "confirmed",
120
+ maxSupportedTransactionVersion: 0
121
+ });
122
+ return {
123
+ success: true,
124
+ signature,
125
+ confirmedAt: txDetails?.blockTime ?? Math.floor(Date.now() / 1e3),
126
+ slot: txDetails?.slot ?? confirmation.context.slot,
127
+ amountLamports,
128
+ amountSol: Number(amountLamports) / LAMPORTS_PER_SOL
129
+ };
130
+ } catch (error) {
131
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
132
+ return {
133
+ success: false,
134
+ error: errorMessage
135
+ };
136
+ }
137
+ }
138
+ async function getAgentBalance(connection, agentKeypair) {
139
+ const balance = await connection.getBalance(agentKeypair.publicKey);
140
+ return {
141
+ balance: BigInt(balance),
142
+ balanceSol: balance / LAMPORTS_PER_SOL
143
+ };
144
+ }
145
+ async function hasAgentSufficientBalance(connection, agentKeypair, requiredLamports) {
146
+ const { balance } = await getAgentBalance(connection, agentKeypair);
147
+ const totalRequired = requiredLamports + 10000n;
148
+ return {
149
+ sufficient: balance >= totalRequired,
150
+ balance,
151
+ required: totalRequired
152
+ };
153
+ }
154
+ function keypairFromBase58(base58Secret) {
155
+ const bytes = Buffer.from(base58Secret, "base64");
156
+ if (bytes.length !== 64) {
157
+ const parts = base58Secret.split(",").map((n) => parseInt(n.trim(), 10));
158
+ if (parts.length === 64) {
159
+ return Keypair.fromSecretKey(Uint8Array.from(parts));
160
+ }
161
+ throw new Error("Invalid secret key format. Expected base58 string or comma-separated bytes.");
162
+ }
163
+ return Keypair.fromSecretKey(bytes);
164
+ }
165
+ function generateAgentKeypair() {
166
+ const keypair = Keypair.generate();
167
+ const secretBytes = Array.from(keypair.secretKey);
168
+ return {
169
+ keypair,
170
+ secretBase58: secretBytes.join(","),
171
+ // Comma-separated for easy storage
172
+ publicKey: keypair.publicKey.toBase58()
173
+ };
174
+ }
175
+ var MAX_CREDITS = 1e3;
176
+ var MIN_SECRET_LENGTH = 32;
177
+ function getSecretKey(secret) {
178
+ if (!secret || typeof secret !== "string") {
179
+ throw new Error("Session secret is required");
180
+ }
181
+ if (secret.length < MIN_SECRET_LENGTH) {
182
+ throw new Error(`Session secret must be at least ${MIN_SECRET_LENGTH} characters`);
183
+ }
184
+ return new TextEncoder().encode(secret);
185
+ }
186
+ function validateWalletAddress(address) {
187
+ if (!address || typeof address !== "string") return false;
188
+ const base58Regex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
189
+ return base58Regex.test(address);
190
+ }
191
+ async function createCreditSession(walletAddress, purchaseId, config) {
192
+ if (!validateWalletAddress(walletAddress)) {
193
+ throw new Error("Invalid wallet address format");
194
+ }
195
+ if (config.initialCredits <= 0 || config.initialCredits > MAX_CREDITS) {
196
+ throw new Error(`Credits must be between 1 and ${MAX_CREDITS}`);
197
+ }
198
+ if (!config.durationHours || config.durationHours <= 0 || config.durationHours > 8760) {
199
+ throw new Error("Session duration must be between 1 and 8760 hours (1 year)");
200
+ }
201
+ const sessionId = v4();
202
+ const now = Math.floor(Date.now() / 1e3);
203
+ const expiresAt = now + config.durationHours * 3600;
204
+ const bundleExpiry = config.bundleExpiryHours ? now + config.bundleExpiryHours * 3600 : expiresAt;
205
+ const session = {
206
+ id: sessionId,
207
+ walletAddress,
208
+ unlockedArticles: [purchaseId],
209
+ siteWideUnlock: false,
210
+ createdAt: now,
211
+ expiresAt,
212
+ credits: config.initialCredits,
213
+ bundleExpiry,
214
+ bundleType: config.bundleType
215
+ };
216
+ const payload = {
217
+ sub: walletAddress,
218
+ sid: sessionId,
219
+ articles: session.unlockedArticles,
220
+ siteWide: false,
221
+ credits: config.initialCredits,
222
+ bundleExpiry,
223
+ bundleType: config.bundleType,
224
+ iat: now,
225
+ exp: expiresAt
226
+ };
227
+ const token = await new SignJWT(payload).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime(`${config.durationHours}h`).sign(getSecretKey(config.secret));
228
+ return { token, session };
229
+ }
230
+ async function validateCreditSession(token, secret) {
231
+ if (!token || typeof token !== "string") {
232
+ return { valid: false, reason: "Invalid token format" };
233
+ }
234
+ try {
235
+ const { payload } = await jwtVerify(token, getSecretKey(secret));
236
+ const creditPayload = payload;
237
+ if (!creditPayload.sub || !creditPayload.sid || !creditPayload.exp) {
238
+ return { valid: false, reason: "Malformed session payload" };
239
+ }
240
+ const now = Math.floor(Date.now() / 1e3);
241
+ if (creditPayload.exp < now) {
242
+ return { valid: false, reason: "Session expired" };
243
+ }
244
+ if (creditPayload.bundleExpiry && creditPayload.bundleExpiry < now) {
245
+ return { valid: false, reason: "Bundle expired" };
246
+ }
247
+ if (!validateWalletAddress(creditPayload.sub)) {
248
+ return { valid: false, reason: "Invalid session data" };
249
+ }
250
+ const session = {
251
+ id: creditPayload.sid,
252
+ walletAddress: creditPayload.sub,
253
+ unlockedArticles: Array.isArray(creditPayload.articles) ? creditPayload.articles : [],
254
+ siteWideUnlock: Boolean(creditPayload.siteWide),
255
+ createdAt: creditPayload.iat ?? 0,
256
+ expiresAt: creditPayload.exp,
257
+ credits: creditPayload.credits ?? 0,
258
+ bundleExpiry: creditPayload.bundleExpiry,
259
+ bundleType: creditPayload.bundleType
260
+ };
261
+ return { valid: true, session };
262
+ } catch {
263
+ return { valid: false, reason: "Invalid session" };
264
+ }
265
+ }
266
+ async function useCredit(token, secret, creditsToUse = 1) {
267
+ if (creditsToUse <= 0) {
268
+ return { success: false, remainingCredits: 0, error: "Invalid credit amount" };
269
+ }
270
+ const validation = await validateCreditSession(token, secret);
271
+ if (!validation.valid || !validation.session) {
272
+ return {
273
+ success: false,
274
+ remainingCredits: 0,
275
+ error: validation.reason || "Invalid session"
276
+ };
277
+ }
278
+ const session = validation.session;
279
+ if (session.credits < creditsToUse) {
280
+ return {
281
+ success: false,
282
+ remainingCredits: session.credits,
283
+ error: "Insufficient credits"
284
+ };
285
+ }
286
+ const newCredits = session.credits - creditsToUse;
287
+ const payload = {
288
+ sub: session.walletAddress,
289
+ sid: session.id,
290
+ articles: session.unlockedArticles,
291
+ siteWide: session.siteWideUnlock,
292
+ credits: newCredits,
293
+ bundleExpiry: session.bundleExpiry,
294
+ bundleType: session.bundleType,
295
+ iat: session.createdAt,
296
+ exp: session.expiresAt
297
+ };
298
+ const newToken = await new SignJWT(payload).setProtectedHeader({ alg: "HS256" }).sign(getSecretKey(secret));
299
+ return {
300
+ success: true,
301
+ remainingCredits: newCredits,
302
+ newToken
303
+ };
304
+ }
305
+ async function addCredits(token, secret, creditsToAdd) {
306
+ if (creditsToAdd <= 0 || creditsToAdd > MAX_CREDITS) {
307
+ return { success: false, error: "Invalid credit amount" };
308
+ }
309
+ const validation = await validateCreditSession(token, secret);
310
+ if (!validation.valid || !validation.session) {
311
+ return { success: false, error: validation.reason || "Invalid session" };
312
+ }
313
+ const session = validation.session;
314
+ const newCredits = Math.min(session.credits + creditsToAdd, MAX_CREDITS);
315
+ const payload = {
316
+ sub: session.walletAddress,
317
+ sid: session.id,
318
+ articles: session.unlockedArticles,
319
+ siteWide: session.siteWideUnlock,
320
+ credits: newCredits,
321
+ bundleExpiry: session.bundleExpiry,
322
+ bundleType: session.bundleType,
323
+ iat: session.createdAt,
324
+ exp: session.expiresAt
325
+ };
326
+ const newToken = await new SignJWT(payload).setProtectedHeader({ alg: "HS256" }).sign(getSecretKey(secret));
327
+ return {
328
+ success: true,
329
+ newToken,
330
+ totalCredits: newCredits
331
+ };
332
+ }
333
+ async function getRemainingCredits(token, secret) {
334
+ const validation = await validateCreditSession(token, secret);
335
+ if (!validation.valid || !validation.session) {
336
+ return { credits: 0, valid: false };
337
+ }
338
+ return {
339
+ credits: validation.session.credits,
340
+ valid: true,
341
+ bundleExpiry: validation.session.bundleExpiry
342
+ };
343
+ }
344
+
345
+ export { addCredits, createCreditSession, executeAgentPayment, generateAgentKeypair, getAgentBalance, getRemainingCredits, hasAgentSufficientBalance, keypairFromBase58, useCredit, validateCreditSession };
346
+ //# sourceMappingURL=index.js.map
347
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/agent/solanaHelpers.ts","../../src/agent/agentPayment.ts","../../src/agent/credits.ts"],"names":["PublicKey","uuidv4"],"mappings":"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","file":"index.js","sourcesContent":["// Solana Helper Utilities for Agent Module\n// Self-contained helpers to avoid dependency on deleted/replaced modules\n\nimport {\n Connection,\n PublicKey,\n TransactionMessage,\n VersionedTransaction,\n ComputeBudgetProgram,\n type TransactionInstruction,\n} from '@solana/web3.js';\n\n/** Configuration for priority fees */\nexport interface PriorityFeeConfig {\n /** Enable priority fees (default: false) */\n enabled?: boolean;\n /** Price per compute unit in micro-lamports (default: auto-estimate) */\n microLamports?: number;\n /** Maximum compute units for transaction (default: 200_000) */\n computeUnits?: number;\n}\n\n/** Default priority fee settings */\nconst DEFAULT_COMPUTE_UNITS = 200_000;\nconst DEFAULT_MICRO_LAMPORTS = 1_000; // 0.001 lamports per CU\n\n/**\n * Create compute budget instructions for priority fees\n */\nexport function createPriorityFeeInstructions(\n config: PriorityFeeConfig = {}\n): TransactionInstruction[] {\n const { enabled = false, microLamports, computeUnits } = config;\n\n if (!enabled) {\n return [];\n }\n\n const instructions: TransactionInstruction[] = [];\n\n // Set compute unit limit\n const units = computeUnits ?? DEFAULT_COMPUTE_UNITS;\n instructions.push(ComputeBudgetProgram.setComputeUnitLimit({ units }));\n\n // Set compute unit price\n const price = microLamports ?? DEFAULT_MICRO_LAMPORTS;\n instructions.push(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: price }));\n\n return instructions;\n}\n\n/** Configuration for building versioned transactions */\nexport interface VersionedTransactionConfig {\n connection: Connection;\n payer: PublicKey;\n instructions: TransactionInstruction[];\n priorityFee?: PriorityFeeConfig;\n recentBlockhash?: string;\n}\n\n/** Result of building a versioned transaction */\nexport interface VersionedTransactionResult {\n transaction: VersionedTransaction;\n blockhash: string;\n lastValidBlockHeight: number;\n}\n\n/**\n * Build a versioned transaction (v0) with optional priority fees\n */\nexport async function buildVersionedTransaction(\n config: VersionedTransactionConfig\n): Promise<VersionedTransactionResult> {\n const {\n connection,\n payer,\n instructions,\n priorityFee,\n recentBlockhash,\n } = config;\n\n // Prepend priority fee instructions if configured\n const priorityIxs = createPriorityFeeInstructions(priorityFee);\n const allInstructions = [...priorityIxs, ...instructions];\n\n // Get recent blockhash if not provided\n let blockhash: string;\n let lastValidBlockHeight: number;\n\n if (recentBlockhash) {\n blockhash = recentBlockhash;\n // Estimate last valid block height (typically ~150 blocks)\n const slot = await connection.getSlot();\n lastValidBlockHeight = slot + 150;\n } else {\n const latestBlockhash = await connection.getLatestBlockhash('confirmed');\n blockhash = latestBlockhash.blockhash;\n lastValidBlockHeight = latestBlockhash.lastValidBlockHeight;\n }\n\n // Build message\n const message = new TransactionMessage({\n payerKey: payer,\n recentBlockhash: blockhash,\n instructions: allInstructions,\n }).compileToV0Message([]);\n\n // Create versioned transaction\n const transaction = new VersionedTransaction(message);\n\n return {\n transaction,\n blockhash,\n lastValidBlockHeight,\n };\n}\n","// Agent Payment Utilities\n// Server-side autonomous payment execution for AI agents\n// SECURITY: Keypair must only be loaded server-side\n\nimport {\n Connection,\n Keypair,\n PublicKey,\n SystemProgram,\n LAMPORTS_PER_SOL,\n} from '@solana/web3.js';\nimport { buildVersionedTransaction, type PriorityFeeConfig } from './solanaHelpers';\n\n/** Parameters for executing an agent payment */\nexport interface ExecuteAgentPaymentParams {\n /** Solana connection */\n connection: Connection;\n /** Agent's keypair (server-side only!) */\n agentKeypair: Keypair;\n /** Recipient wallet address (base58) */\n recipientAddress: string;\n /** Amount to send in lamports */\n amountLamports: bigint;\n /** Optional memo for the transaction */\n memo?: string;\n /** Optional priority fee configuration */\n priorityFee?: PriorityFeeConfig;\n /** Timeout for confirmation in ms (default: 60000) */\n confirmationTimeout?: number;\n}\n\n/** Result of an agent payment execution */\nexport interface AgentPaymentResult {\n /** Whether the payment was successful */\n success: boolean;\n /** Transaction signature (if successful) */\n signature?: string;\n /** Error message (if failed) */\n error?: string;\n /** Block time when confirmed (Unix timestamp) */\n confirmedAt?: number;\n /** Slot number */\n slot?: number;\n /** Amount sent in lamports */\n amountLamports?: bigint;\n /** Amount sent in SOL */\n amountSol?: number;\n}\n\n// Wallet address validation regex\nconst WALLET_REGEX = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n\n/**\n * Validate wallet address format\n */\nfunction isValidWalletAddress(address: string): boolean {\n if (!address || typeof address !== 'string') return false;\n return WALLET_REGEX.test(address);\n}\n\n/**\n * Execute an autonomous SOL payment from the agent's wallet\n * \n * This is the core utility for AI agents to pay for x402-protected resources.\n * The agent keypair must be loaded server-side only (never exposed to client).\n * \n * @example\n * ```typescript\n * import { executeAgentPayment } from '@alleyboss/micropay-solana-x402-paywall/agent';\n * import { Keypair, Connection } from '@solana/web3.js';\n * import bs58 from 'bs58';\n * \n * // Load agent keypair from environment (server-side only!)\n * const agentKeypair = Keypair.fromSecretKey(\n * bs58.decode(process.env.AGENT_KEYPAIR_SECRET!)\n * );\n * \n * const connection = new Connection('https://api.devnet.solana.com');\n * \n * const result = await executeAgentPayment({\n * connection,\n * agentKeypair,\n * recipientAddress: 'RecipientWallet...',\n * amountLamports: 20_000_000n, // 0.02 SOL\n * priorityFee: { enabled: true, microLamports: 5000 },\n * });\n * \n * if (result.success) {\n * console.log('Payment sent:', result.signature);\n * }\n * ```\n */\nexport async function executeAgentPayment(\n params: ExecuteAgentPaymentParams\n): Promise<AgentPaymentResult> {\n const {\n connection,\n agentKeypair,\n recipientAddress,\n amountLamports,\n priorityFee,\n confirmationTimeout = 60000,\n } = params;\n\n // Validate recipient address\n if (!isValidWalletAddress(recipientAddress)) {\n return {\n success: false,\n error: 'Invalid recipient address format',\n };\n }\n\n // Validate amount\n if (amountLamports <= 0n) {\n return {\n success: false,\n error: 'Amount must be greater than 0',\n };\n }\n\n try {\n const recipientPubkey = new PublicKey(recipientAddress);\n\n // Create transfer instruction\n const transferInstruction = SystemProgram.transfer({\n fromPubkey: agentKeypair.publicKey,\n toPubkey: recipientPubkey,\n lamports: amountLamports,\n });\n\n // Build versioned transaction with optional priority fee\n const { transaction, lastValidBlockHeight } = await buildVersionedTransaction({\n connection,\n payer: agentKeypair.publicKey,\n instructions: [transferInstruction],\n priorityFee,\n });\n\n // Sign transaction\n transaction.sign([agentKeypair]);\n\n // Send transaction\n const signature = await connection.sendTransaction(transaction, {\n maxRetries: 3,\n skipPreflight: false,\n });\n\n // Wait for confirmation with timeout\n const confirmationPromise = connection.confirmTransaction(\n {\n signature,\n lastValidBlockHeight,\n blockhash: transaction.message.recentBlockhash,\n },\n 'confirmed'\n );\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error('Confirmation timeout')), confirmationTimeout);\n });\n\n const confirmation = await Promise.race([confirmationPromise, timeoutPromise]);\n\n if (confirmation.value.err) {\n return {\n success: false,\n signature,\n error: 'Transaction failed on-chain',\n };\n }\n\n // Get transaction details for confirmed time\n const txDetails = await connection.getTransaction(signature, {\n commitment: 'confirmed',\n maxSupportedTransactionVersion: 0,\n });\n\n return {\n success: true,\n signature,\n confirmedAt: txDetails?.blockTime ?? Math.floor(Date.now() / 1000),\n slot: txDetails?.slot ?? confirmation.context.slot,\n amountLamports,\n amountSol: Number(amountLamports) / LAMPORTS_PER_SOL,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n error: errorMessage,\n };\n }\n}\n\n/**\n * Get the agent wallet's SOL balance\n */\nexport async function getAgentBalance(\n connection: Connection,\n agentKeypair: Keypair\n): Promise<{ balance: bigint; balanceSol: number }> {\n const balance = await connection.getBalance(agentKeypair.publicKey);\n return {\n balance: BigInt(balance),\n balanceSol: balance / LAMPORTS_PER_SOL,\n };\n}\n\n/**\n * Check if agent has sufficient balance for a payment\n */\nexport async function hasAgentSufficientBalance(\n connection: Connection,\n agentKeypair: Keypair,\n requiredLamports: bigint\n): Promise<{ sufficient: boolean; balance: bigint; required: bigint }> {\n const { balance } = await getAgentBalance(connection, agentKeypair);\n // Add buffer for transaction fees (~5000 lamports)\n const totalRequired = requiredLamports + 10000n;\n return {\n sufficient: balance >= totalRequired,\n balance,\n required: totalRequired,\n };\n}\n\n/**\n * Create a Keypair from a base58-encoded secret key string\n * \n * @example\n * ```typescript\n * const keypair = keypairFromBase58(process.env.AGENT_KEYPAIR_SECRET!);\n * ```\n */\nexport function keypairFromBase58(base58Secret: string): Keypair {\n // Dynamic import to avoid bundling bs58 in client code\n // For server-side use, install bs58 as a dependency\n const bytes = Buffer.from(base58Secret, 'base64');\n\n // Try base58 decode if base64 fails\n if (bytes.length !== 64) {\n // Fallback: assume it's a comma-separated array of numbers\n const parts = base58Secret.split(',').map(n => parseInt(n.trim(), 10));\n if (parts.length === 64) {\n return Keypair.fromSecretKey(Uint8Array.from(parts));\n }\n throw new Error('Invalid secret key format. Expected base58 string or comma-separated bytes.');\n }\n\n return Keypair.fromSecretKey(bytes);\n}\n\n/**\n * Create a new random Keypair for agent use\n * Returns both the keypair and its base58-encoded secret for storage\n */\nexport function generateAgentKeypair(): { keypair: Keypair; secretBase58: string; publicKey: string } {\n const keypair = Keypair.generate();\n const secretBytes = Array.from(keypair.secretKey);\n return {\n keypair,\n secretBase58: secretBytes.join(','), // Comma-separated for easy storage\n publicKey: keypair.publicKey.toBase58(),\n };\n}\n","// Bundle Credits System\n// Optional credit-based session management for agent payments\n\nimport { SignJWT, jwtVerify } from 'jose';\nimport { v4 as uuidv4 } from 'uuid';\nimport type { SessionConfig, SessionData } from '../session/types';\n\n/** Credit claims stored in session JWT */\nexport interface CreditSessionClaims {\n /** Number of remaining credits */\n credits: number;\n /** Unix timestamp when bundle expires (optional) */\n bundleExpiry?: number;\n /** Bundle type identifier (e.g., 'starter', 'pro') */\n bundleType?: string;\n}\n\n/** Extended session data with credit information */\nexport type CreditSessionData = SessionData & CreditSessionClaims;\n\n/** Configuration for credit sessions */\nexport interface CreditSessionConfig extends SessionConfig {\n /** Initial number of credits */\n initialCredits: number;\n /** Bundle expiry in hours (optional, defaults to session duration) */\n bundleExpiryHours?: number;\n /** Bundle type identifier */\n bundleType?: string;\n}\n\n/** JWT payload for credit sessions */\ninterface CreditJWTPayload {\n sub: string;\n sid: string;\n articles: string[];\n siteWide: boolean;\n credits: number;\n bundleExpiry?: number;\n bundleType?: string;\n iat: number;\n exp: number;\n}\n\n// Constants\nconst MAX_CREDITS = 1000;\nconst MIN_SECRET_LENGTH = 32;\n\n/**\n * Get the secret key for JWT signing\n */\nfunction getSecretKey(secret: string): Uint8Array {\n if (!secret || typeof secret !== 'string') {\n throw new Error('Session secret is required');\n }\n if (secret.length < MIN_SECRET_LENGTH) {\n throw new Error(`Session secret must be at least ${MIN_SECRET_LENGTH} characters`);\n }\n return new TextEncoder().encode(secret);\n}\n\n/**\n * Validate wallet address format\n */\nfunction validateWalletAddress(address: string): boolean {\n if (!address || typeof address !== 'string') return false;\n const base58Regex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n return base58Regex.test(address);\n}\n\n/**\n * Create a new credit session after bundle purchase\n * \n * @example\n * ```typescript\n * import { createCreditSession } from '@alleyboss/micropay-solana-x402-paywall/agent';\n * \n * const { token, session } = await createCreditSession(\n * walletAddress,\n * 'bundle-purchase',\n * {\n * secret: process.env.SESSION_SECRET!,\n * durationHours: 24 * 30, // 30 days\n * initialCredits: 10,\n * bundleType: 'starter',\n * }\n * );\n * \n * // Set as cookie\n * response.cookies.set('x402_credits', token, { httpOnly: true });\n * ```\n */\nexport async function createCreditSession(\n walletAddress: string,\n purchaseId: string,\n config: CreditSessionConfig\n): Promise<{ token: string; session: CreditSessionData }> {\n // Input validation\n if (!validateWalletAddress(walletAddress)) {\n throw new Error('Invalid wallet address format');\n }\n if (config.initialCredits <= 0 || config.initialCredits > MAX_CREDITS) {\n throw new Error(`Credits must be between 1 and ${MAX_CREDITS}`);\n }\n if (!config.durationHours || config.durationHours <= 0 || config.durationHours > 8760) {\n throw new Error('Session duration must be between 1 and 8760 hours (1 year)');\n }\n\n const sessionId = uuidv4();\n const now = Math.floor(Date.now() / 1000);\n const expiresAt = now + (config.durationHours * 3600);\n const bundleExpiry = config.bundleExpiryHours\n ? now + (config.bundleExpiryHours * 3600)\n : expiresAt;\n\n const session: CreditSessionData = {\n id: sessionId,\n walletAddress,\n unlockedArticles: [purchaseId],\n siteWideUnlock: false,\n createdAt: now,\n expiresAt,\n credits: config.initialCredits,\n bundleExpiry,\n bundleType: config.bundleType,\n };\n\n const payload: CreditJWTPayload = {\n sub: walletAddress,\n sid: sessionId,\n articles: session.unlockedArticles,\n siteWide: false,\n credits: config.initialCredits,\n bundleExpiry,\n bundleType: config.bundleType,\n iat: now,\n exp: expiresAt,\n };\n\n const token = await new SignJWT(payload as unknown as Record<string, unknown>)\n .setProtectedHeader({ alg: 'HS256' })\n .setIssuedAt()\n .setExpirationTime(`${config.durationHours}h`)\n .sign(getSecretKey(config.secret));\n\n return { token, session };\n}\n\n/** Result of validating a credit session */\nexport interface CreditValidation {\n valid: boolean;\n session?: CreditSessionData;\n reason?: string;\n}\n\n/**\n * Validate a credit session token\n */\nexport async function validateCreditSession(\n token: string,\n secret: string\n): Promise<CreditValidation> {\n if (!token || typeof token !== 'string') {\n return { valid: false, reason: 'Invalid token format' };\n }\n\n try {\n const { payload } = await jwtVerify(token, getSecretKey(secret));\n const creditPayload = payload as unknown as CreditJWTPayload;\n\n // Validate required fields\n if (!creditPayload.sub || !creditPayload.sid || !creditPayload.exp) {\n return { valid: false, reason: 'Malformed session payload' };\n }\n\n // Check expiration\n const now = Math.floor(Date.now() / 1000);\n if (creditPayload.exp < now) {\n return { valid: false, reason: 'Session expired' };\n }\n\n // Check bundle expiry if set\n if (creditPayload.bundleExpiry && creditPayload.bundleExpiry < now) {\n return { valid: false, reason: 'Bundle expired' };\n }\n\n // Validate wallet format\n if (!validateWalletAddress(creditPayload.sub)) {\n return { valid: false, reason: 'Invalid session data' };\n }\n\n const session: CreditSessionData = {\n id: creditPayload.sid,\n walletAddress: creditPayload.sub,\n unlockedArticles: Array.isArray(creditPayload.articles) ? creditPayload.articles : [],\n siteWideUnlock: Boolean(creditPayload.siteWide),\n createdAt: creditPayload.iat ?? 0,\n expiresAt: creditPayload.exp,\n credits: creditPayload.credits ?? 0,\n bundleExpiry: creditPayload.bundleExpiry,\n bundleType: creditPayload.bundleType,\n };\n\n return { valid: true, session };\n } catch {\n return { valid: false, reason: 'Invalid session' };\n }\n}\n\n/** Result of using a credit */\nexport interface UseCreditResult {\n /** Whether the credit was successfully used */\n success: boolean;\n /** Remaining credits after use */\n remainingCredits: number;\n /** New token with decremented credits (if successful) */\n newToken?: string;\n /** Error message (if failed) */\n error?: string;\n}\n\n/**\n * Use one credit from the session\n * Returns a new token with decremented credit count\n * \n * @example\n * ```typescript\n * import { useCredit } from '@alleyboss/micropay-solana-x402-paywall/agent';\n * \n * const result = await useCredit(token, process.env.SESSION_SECRET!);\n * \n * if (result.success) {\n * console.log(`Credit used. ${result.remainingCredits} remaining`);\n * // Update cookie with new token\n * response.cookies.set('x402_credits', result.newToken!);\n * } else {\n * console.log('No credits:', result.error);\n * }\n * ```\n */\nexport async function useCredit(\n token: string,\n secret: string,\n creditsToUse: number = 1\n): Promise<UseCreditResult> {\n if (creditsToUse <= 0) {\n return { success: false, remainingCredits: 0, error: 'Invalid credit amount' };\n }\n\n const validation = await validateCreditSession(token, secret);\n\n if (!validation.valid || !validation.session) {\n return {\n success: false,\n remainingCredits: 0,\n error: validation.reason || 'Invalid session'\n };\n }\n\n const session = validation.session;\n\n // Check if enough credits\n if (session.credits < creditsToUse) {\n return {\n success: false,\n remainingCredits: session.credits,\n error: 'Insufficient credits'\n };\n }\n\n // Decrement credits and create new token\n const newCredits = session.credits - creditsToUse;\n\n const payload: CreditJWTPayload = {\n sub: session.walletAddress,\n sid: session.id,\n articles: session.unlockedArticles,\n siteWide: session.siteWideUnlock,\n credits: newCredits,\n bundleExpiry: session.bundleExpiry,\n bundleType: session.bundleType,\n iat: session.createdAt,\n exp: session.expiresAt,\n };\n\n const newToken = await new SignJWT(payload as unknown as Record<string, unknown>)\n .setProtectedHeader({ alg: 'HS256' })\n .sign(getSecretKey(secret));\n\n return {\n success: true,\n remainingCredits: newCredits,\n newToken,\n };\n}\n\n/**\n * Add credits to an existing session\n * Useful for top-ups or rewards\n */\nexport async function addCredits(\n token: string,\n secret: string,\n creditsToAdd: number\n): Promise<{ success: boolean; newToken?: string; totalCredits?: number; error?: string }> {\n if (creditsToAdd <= 0 || creditsToAdd > MAX_CREDITS) {\n return { success: false, error: 'Invalid credit amount' };\n }\n\n const validation = await validateCreditSession(token, secret);\n\n if (!validation.valid || !validation.session) {\n return { success: false, error: validation.reason || 'Invalid session' };\n }\n\n const session = validation.session;\n const newCredits = Math.min(session.credits + creditsToAdd, MAX_CREDITS);\n\n const payload: CreditJWTPayload = {\n sub: session.walletAddress,\n sid: session.id,\n articles: session.unlockedArticles,\n siteWide: session.siteWideUnlock,\n credits: newCredits,\n bundleExpiry: session.bundleExpiry,\n bundleType: session.bundleType,\n iat: session.createdAt,\n exp: session.expiresAt,\n };\n\n const newToken = await new SignJWT(payload as unknown as Record<string, unknown>)\n .setProtectedHeader({ alg: 'HS256' })\n .sign(getSecretKey(secret));\n\n return {\n success: true,\n newToken,\n totalCredits: newCredits,\n };\n}\n\n/**\n * Get remaining credits from a session token (quick check without full validation)\n */\nexport async function getRemainingCredits(\n token: string,\n secret: string\n): Promise<{ credits: number; valid: boolean; bundleExpiry?: number }> {\n const validation = await validateCreditSession(token, secret);\n\n if (!validation.valid || !validation.session) {\n return { credits: 0, valid: false };\n }\n\n return {\n credits: validation.session.credits,\n valid: true,\n bundleExpiry: validation.session.bundleExpiry,\n };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // src/types/payment.ts
3
+ // src/client/types.ts
4
4
  var TOKEN_MINTS = {
5
5
  /** USDC on mainnet */
6
6
  USDC_MAINNET: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/payment.ts","../../src/client/payment.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["// Payment-related TypeScript types for x402 protocol\n\n/** x402 network identifiers for Solana */\nexport type X402Network = 'solana-devnet' | 'solana-mainnet';\n\n/** Solana network types */\nexport type SolanaNetwork = 'devnet' | 'mainnet-beta';\n\n/** SPL Token asset specification */\nexport interface SPLTokenAsset {\n /** Token mint address */\n mint: string;\n /** Token decimals (default: 6 for USDC/USDT) */\n decimals?: number;\n}\n\n/** Asset types for payments */\nexport type PaymentAsset = 'native' | 'usdc' | 'usdt' | SPLTokenAsset;\n\n/** Known SPL token mint addresses */\nexport const TOKEN_MINTS = {\n /** USDC on mainnet */\n USDC_MAINNET: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',\n /** USDC on devnet */\n USDC_DEVNET: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',\n /** USDT on mainnet */\n USDT_MAINNET: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',\n} as const;\n\n/** Payment requirement for x402 protocol */\nexport interface PaymentRequirement {\n /** Payment scheme - currently only 'exact' is supported */\n scheme: 'exact';\n /** Network identifier for x402 */\n network: X402Network;\n /** Amount in smallest unit as string (lamports for SOL, base units for tokens) */\n maxAmountRequired: string;\n /** URL of the protected resource */\n resource: string;\n /** Human-readable description */\n description: string;\n /** MIME type of the resource */\n mimeType?: string;\n /** Recipient wallet address */\n payTo: string;\n /** Maximum time in seconds to complete payment */\n maxTimeoutSeconds: number;\n /** Asset type - 'native' for SOL, 'usdc', 'usdt', or custom mint */\n asset: PaymentAsset;\n /** Additional metadata */\n extra?: {\n name?: string;\n articleId?: string;\n [key: string]: unknown;\n };\n}\n\n/** Payment payload sent by client after transaction */\nexport interface PaymentPayload {\n /** x402 protocol version */\n x402Version: number;\n /** Payment scheme */\n scheme: 'exact';\n /** Network identifier */\n network: X402Network;\n /** Transaction details */\n payload: {\n /** Transaction signature (base58) */\n signature: string;\n /** Base64 encoded transaction (optional) */\n transaction?: string;\n };\n}\n\n/** Request to verify a payment */\nexport interface VerificationRequest {\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirement;\n}\n\n/** Response from payment verification */\nexport interface VerificationResponse {\n /** Whether the payment is valid */\n valid: boolean;\n /** Reason for invalid payment */\n invalidReason?: string;\n /** Whether the transaction is settled on-chain */\n settled?: boolean;\n /** Sender wallet address (payer) */\n from?: string;\n /** Transaction details */\n transaction?: {\n signature: string;\n blockTime?: number;\n slot?: number;\n };\n}\n\n/** Payment status for tracking */\nexport interface PaymentStatus {\n status: 'pending' | 'confirmed' | 'failed' | 'expired';\n signature?: string;\n confirmations?: number;\n error?: string;\n}\n\n/** x402 HTTP header constants */\nexport const X402_HEADERS = {\n PAYMENT_REQUIRED: 'x-payment-required',\n PAYMENT: 'x-payment',\n PAYMENT_RESPONSE: 'x-payment-response',\n} as const;\n\n/** Configuration for article pricing */\nexport interface ArticlePaymentConfig {\n articleId: string;\n priceInLamports: bigint;\n title: string;\n description?: string;\n}\n","// Client-Side Payment Flow Helper\n// Headless payment flow for frontend integration (no Node.js dependencies)\n\nimport { TOKEN_MINTS, type PaymentAsset, type SolanaNetwork } from '../types';\n\n/**\n * Payment flow configuration\n */\nexport interface PaymentFlowConfig {\n /** Solana network */\n network: SolanaNetwork;\n /** Recipient wallet address */\n recipientWallet: string;\n /** Amount in smallest unit (lamports or token base units) */\n amount: bigint;\n /** Asset to pay with */\n asset?: PaymentAsset;\n /** Optional memo for the transaction */\n memo?: string;\n}\n\n/**\n * Solana Pay URL parameters\n */\nexport interface SolanaPayUrlParams {\n /** Recipient address */\n recipient: string;\n /** Amount in token's natural units (e.g., SOL, not lamports) */\n amount?: number;\n /** SPL token mint address */\n splToken?: string;\n /** Transaction reference */\n reference?: string;\n /** Label for the recipient */\n label?: string;\n /** Memo/message */\n message?: string;\n}\n\n/**\n * Build a Solana Pay URL for QR codes and deep linking\n * Compatible with Phantom, Solflare, and other Solana Pay wallets\n * \n * @example\n * ```typescript\n * const url = buildSolanaPayUrl({\n * recipient: 'CreatorWalletAddress',\n * amount: 0.01,\n * label: 'Article Unlock',\n * message: 'Premium Content Access',\n * });\n * // Returns: solana:CreatorWalletAddress?amount=0.01&label=Article%20Unlock&message=Premium%20Content%20Access\n * ```\n */\nexport function buildSolanaPayUrl(params: SolanaPayUrlParams): string {\n const { recipient, amount, splToken, reference, label, message } = params;\n\n const url = new URL(`solana:${recipient}`);\n\n if (amount !== undefined) {\n url.searchParams.set('amount', amount.toString());\n }\n\n if (splToken) {\n url.searchParams.set('spl-token', splToken);\n }\n\n if (reference) {\n url.searchParams.set('reference', reference);\n }\n\n if (label) {\n url.searchParams.set('label', label);\n }\n\n if (message) {\n url.searchParams.set('message', message);\n }\n\n return url.toString();\n}\n\n/**\n * Create a payment flow helper for frontend use\n * Provides utilities for building transactions and generating QR codes\n * \n * @example\n * ```typescript\n * const flow = createPaymentFlow({\n * network: 'devnet',\n * recipientWallet: 'CreatorAddress',\n * amount: 10000000n, // 0.01 SOL\n * });\n * \n * // Generate QR code URL\n * const qrUrl = flow.getSolanaPayUrl({ label: 'Unlock Article' });\n * \n * // Get transaction amount in natural units\n * const amountInSol = flow.getDisplayAmount();\n * ```\n */\nexport function createPaymentFlow(config: PaymentFlowConfig) {\n const { network, recipientWallet, amount, asset = 'native', memo } = config;\n\n // Determine decimals and mint\n let decimals = 9; // SOL default\n let mintAddress: string | undefined;\n\n if (asset === 'usdc') {\n decimals = 6;\n mintAddress = network === 'mainnet-beta' ? TOKEN_MINTS.USDC_MAINNET : TOKEN_MINTS.USDC_DEVNET;\n } else if (asset === 'usdt') {\n decimals = 6;\n mintAddress = TOKEN_MINTS.USDT_MAINNET;\n } else if (typeof asset === 'object' && 'mint' in asset) {\n decimals = asset.decimals ?? 6;\n mintAddress = asset.mint;\n }\n\n // Convert to natural units (from lamports/base units)\n const naturalAmount = Number(amount) / Math.pow(10, decimals);\n\n return {\n /** Get the payment configuration */\n getConfig: () => ({ ...config }),\n\n /** Get amount in natural display units (e.g., 0.01 SOL) */\n getDisplayAmount: () => naturalAmount,\n\n /** Get amount formatted with symbol */\n getFormattedAmount: () => {\n const symbol = asset === 'native' ? 'SOL'\n : asset === 'usdc' ? 'USDC'\n : asset === 'usdt' ? 'USDT'\n : 'tokens';\n return `${naturalAmount.toFixed(decimals > 6 ? 4 : 2)} ${symbol}`;\n },\n\n /** Generate Solana Pay URL for QR codes */\n getSolanaPayUrl: (options: { label?: string; reference?: string } = {}) => {\n return buildSolanaPayUrl({\n recipient: recipientWallet,\n amount: naturalAmount,\n splToken: mintAddress,\n label: options.label,\n reference: options.reference,\n message: memo,\n });\n },\n\n /** Get the token mint address (undefined for native SOL) */\n getMintAddress: () => mintAddress,\n\n /** Check if this is a native SOL payment */\n isNativePayment: () => asset === 'native',\n\n /** Get network information */\n getNetworkInfo: () => ({\n network,\n isMainnet: network === 'mainnet-beta',\n explorerUrl: network === 'mainnet-beta'\n ? 'https://explorer.solana.com'\n : 'https://explorer.solana.com?cluster=devnet',\n }),\n\n /** Build explorer URL for a transaction */\n getExplorerUrl: (signature: string) => {\n const baseUrl = 'https://explorer.solana.com/tx';\n const cluster = network === 'mainnet-beta' ? '' : '?cluster=devnet';\n return `${baseUrl}/${signature}${cluster}`;\n },\n };\n}\n\n/**\n * Create a unique reference for payment tracking\n * Uses crypto.randomUUID when available\n */\nexport function createPaymentReference(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // Fallback for environments without crypto.randomUUID\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n"]}
1
+ {"version":3,"sources":["../../src/client/types.ts","../../src/client/payment.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/** SPL Token asset specification */\nexport interface SPLTokenAsset {\n /** Token mint address */\n mint: string;\n /** Token decimals (default: 6 for USDC/USDT) */\n decimals?: number;\n}\n\n/** Asset types for payments */\nexport type PaymentAsset = 'native' | 'usdc' | 'usdt' | SPLTokenAsset;\n\nexport type SolanaNetwork = 'devnet' | 'mainnet-beta';\n\n/** Known SPL token mint addresses */\nexport const TOKEN_MINTS = {\n /** USDC on mainnet */\n USDC_MAINNET: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',\n /** USDC on devnet */\n USDC_DEVNET: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',\n /** USDT on mainnet */\n USDT_MAINNET: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',\n} as const;\n","// Client-Side Payment Flow Helper\n// Headless payment flow for frontend integration (no Node.js dependencies)\n\nimport { TOKEN_MINTS, type PaymentAsset, type SolanaNetwork } from './types';\n\n/**\n * Payment flow configuration\n */\nexport interface PaymentFlowConfig {\n /** Solana network */\n network: SolanaNetwork;\n /** Recipient wallet address */\n recipientWallet: string;\n /** Amount in smallest unit (lamports or token base units) */\n amount: bigint;\n /** Asset to pay with */\n asset?: PaymentAsset;\n /** Optional memo for the transaction */\n memo?: string;\n}\n\n/**\n * Solana Pay URL parameters\n */\nexport interface SolanaPayUrlParams {\n /** Recipient address */\n recipient: string;\n /** Amount in token's natural units (e.g., SOL, not lamports) */\n amount?: number;\n /** SPL token mint address */\n splToken?: string;\n /** Transaction reference */\n reference?: string;\n /** Label for the recipient */\n label?: string;\n /** Memo/message */\n message?: string;\n}\n\n/**\n * Build a Solana Pay URL for QR codes and deep linking\n * Compatible with Phantom, Solflare, and other Solana Pay wallets\n * \n * @example\n * ```typescript\n * const url = buildSolanaPayUrl({\n * recipient: 'CreatorWalletAddress',\n * amount: 0.01,\n * label: 'Article Unlock',\n * message: 'Premium Content Access',\n * });\n * // Returns: solana:CreatorWalletAddress?amount=0.01&label=Article%20Unlock&message=Premium%20Content%20Access\n * ```\n */\nexport function buildSolanaPayUrl(params: SolanaPayUrlParams): string {\n const { recipient, amount, splToken, reference, label, message } = params;\n\n const url = new URL(`solana:${recipient}`);\n\n if (amount !== undefined) {\n url.searchParams.set('amount', amount.toString());\n }\n\n if (splToken) {\n url.searchParams.set('spl-token', splToken);\n }\n\n if (reference) {\n url.searchParams.set('reference', reference);\n }\n\n if (label) {\n url.searchParams.set('label', label);\n }\n\n if (message) {\n url.searchParams.set('message', message);\n }\n\n return url.toString();\n}\n\n/**\n * Create a payment flow helper for frontend use\n * Provides utilities for building transactions and generating QR codes\n * \n * @example\n * ```typescript\n * const flow = createPaymentFlow({\n * network: 'devnet',\n * recipientWallet: 'CreatorAddress',\n * amount: 10000000n, // 0.01 SOL\n * });\n * \n * // Generate QR code URL\n * const qrUrl = flow.getSolanaPayUrl({ label: 'Unlock Article' });\n * \n * // Get transaction amount in natural units\n * const amountInSol = flow.getDisplayAmount();\n * ```\n */\nexport function createPaymentFlow(config: PaymentFlowConfig) {\n const { network, recipientWallet, amount, asset = 'native', memo } = config;\n\n // Determine decimals and mint\n let decimals = 9; // SOL default\n let mintAddress: string | undefined;\n\n if (asset === 'usdc') {\n decimals = 6;\n mintAddress = network === 'mainnet-beta' ? TOKEN_MINTS.USDC_MAINNET : TOKEN_MINTS.USDC_DEVNET;\n } else if (asset === 'usdt') {\n decimals = 6;\n mintAddress = TOKEN_MINTS.USDT_MAINNET;\n } else if (typeof asset === 'object' && 'mint' in asset) {\n decimals = asset.decimals ?? 6;\n mintAddress = asset.mint;\n }\n\n // Convert to natural units (from lamports/base units)\n const naturalAmount = Number(amount) / Math.pow(10, decimals);\n\n return {\n /** Get the payment configuration */\n getConfig: () => ({ ...config }),\n\n /** Get amount in natural display units (e.g., 0.01 SOL) */\n getDisplayAmount: () => naturalAmount,\n\n /** Get amount formatted with symbol */\n getFormattedAmount: () => {\n const symbol = asset === 'native' ? 'SOL'\n : asset === 'usdc' ? 'USDC'\n : asset === 'usdt' ? 'USDT'\n : 'tokens';\n return `${naturalAmount.toFixed(decimals > 6 ? 4 : 2)} ${symbol}`;\n },\n\n /** Generate Solana Pay URL for QR codes */\n getSolanaPayUrl: (options: { label?: string; reference?: string } = {}) => {\n return buildSolanaPayUrl({\n recipient: recipientWallet,\n amount: naturalAmount,\n splToken: mintAddress,\n label: options.label,\n reference: options.reference,\n message: memo,\n });\n },\n\n /** Get the token mint address (undefined for native SOL) */\n getMintAddress: () => mintAddress,\n\n /** Check if this is a native SOL payment */\n isNativePayment: () => asset === 'native',\n\n /** Get network information */\n getNetworkInfo: () => ({\n network,\n isMainnet: network === 'mainnet-beta',\n explorerUrl: network === 'mainnet-beta'\n ? 'https://explorer.solana.com'\n : 'https://explorer.solana.com?cluster=devnet',\n }),\n\n /** Build explorer URL for a transaction */\n getExplorerUrl: (signature: string) => {\n const baseUrl = 'https://explorer.solana.com/tx';\n const cluster = network === 'mainnet-beta' ? '' : '?cluster=devnet';\n return `${baseUrl}/${signature}${cluster}`;\n },\n };\n}\n\n/**\n * Create a unique reference for payment tracking\n * Uses crypto.randomUUID when available\n */\nexport function createPaymentReference(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // Fallback for environments without crypto.randomUUID\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n"]}
@@ -1,4 +1,13 @@
1
- import { S as SolanaNetwork, d as PaymentAsset } from '../payment-BGp7eMQl.cjs';
1
+ /** SPL Token asset specification */
2
+ interface SPLTokenAsset {
3
+ /** Token mint address */
4
+ mint: string;
5
+ /** Token decimals (default: 6 for USDC/USDT) */
6
+ decimals?: number;
7
+ }
8
+ /** Asset types for payments */
9
+ type PaymentAsset = 'native' | 'usdc' | 'usdt' | SPLTokenAsset;
10
+ type SolanaNetwork = 'devnet' | 'mainnet-beta';
2
11
 
3
12
  /**
4
13
  * Payment flow configuration
@@ -1,4 +1,13 @@
1
- import { S as SolanaNetwork, d as PaymentAsset } from '../payment-BGp7eMQl.js';
1
+ /** SPL Token asset specification */
2
+ interface SPLTokenAsset {
3
+ /** Token mint address */
4
+ mint: string;
5
+ /** Token decimals (default: 6 for USDC/USDT) */
6
+ decimals?: number;
7
+ }
8
+ /** Asset types for payments */
9
+ type PaymentAsset = 'native' | 'usdc' | 'usdt' | SPLTokenAsset;
10
+ type SolanaNetwork = 'devnet' | 'mainnet-beta';
2
11
 
3
12
  /**
4
13
  * Payment flow configuration
@@ -1,4 +1,4 @@
1
- // src/types/payment.ts
1
+ // src/client/types.ts
2
2
  var TOKEN_MINTS = {
3
3
  /** USDC on mainnet */
4
4
  USDC_MAINNET: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types/payment.ts","../../src/client/payment.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// Payment-related TypeScript types for x402 protocol\n\n/** x402 network identifiers for Solana */\nexport type X402Network = 'solana-devnet' | 'solana-mainnet';\n\n/** Solana network types */\nexport type SolanaNetwork = 'devnet' | 'mainnet-beta';\n\n/** SPL Token asset specification */\nexport interface SPLTokenAsset {\n /** Token mint address */\n mint: string;\n /** Token decimals (default: 6 for USDC/USDT) */\n decimals?: number;\n}\n\n/** Asset types for payments */\nexport type PaymentAsset = 'native' | 'usdc' | 'usdt' | SPLTokenAsset;\n\n/** Known SPL token mint addresses */\nexport const TOKEN_MINTS = {\n /** USDC on mainnet */\n USDC_MAINNET: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',\n /** USDC on devnet */\n USDC_DEVNET: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',\n /** USDT on mainnet */\n USDT_MAINNET: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',\n} as const;\n\n/** Payment requirement for x402 protocol */\nexport interface PaymentRequirement {\n /** Payment scheme - currently only 'exact' is supported */\n scheme: 'exact';\n /** Network identifier for x402 */\n network: X402Network;\n /** Amount in smallest unit as string (lamports for SOL, base units for tokens) */\n maxAmountRequired: string;\n /** URL of the protected resource */\n resource: string;\n /** Human-readable description */\n description: string;\n /** MIME type of the resource */\n mimeType?: string;\n /** Recipient wallet address */\n payTo: string;\n /** Maximum time in seconds to complete payment */\n maxTimeoutSeconds: number;\n /** Asset type - 'native' for SOL, 'usdc', 'usdt', or custom mint */\n asset: PaymentAsset;\n /** Additional metadata */\n extra?: {\n name?: string;\n articleId?: string;\n [key: string]: unknown;\n };\n}\n\n/** Payment payload sent by client after transaction */\nexport interface PaymentPayload {\n /** x402 protocol version */\n x402Version: number;\n /** Payment scheme */\n scheme: 'exact';\n /** Network identifier */\n network: X402Network;\n /** Transaction details */\n payload: {\n /** Transaction signature (base58) */\n signature: string;\n /** Base64 encoded transaction (optional) */\n transaction?: string;\n };\n}\n\n/** Request to verify a payment */\nexport interface VerificationRequest {\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirement;\n}\n\n/** Response from payment verification */\nexport interface VerificationResponse {\n /** Whether the payment is valid */\n valid: boolean;\n /** Reason for invalid payment */\n invalidReason?: string;\n /** Whether the transaction is settled on-chain */\n settled?: boolean;\n /** Sender wallet address (payer) */\n from?: string;\n /** Transaction details */\n transaction?: {\n signature: string;\n blockTime?: number;\n slot?: number;\n };\n}\n\n/** Payment status for tracking */\nexport interface PaymentStatus {\n status: 'pending' | 'confirmed' | 'failed' | 'expired';\n signature?: string;\n confirmations?: number;\n error?: string;\n}\n\n/** x402 HTTP header constants */\nexport const X402_HEADERS = {\n PAYMENT_REQUIRED: 'x-payment-required',\n PAYMENT: 'x-payment',\n PAYMENT_RESPONSE: 'x-payment-response',\n} as const;\n\n/** Configuration for article pricing */\nexport interface ArticlePaymentConfig {\n articleId: string;\n priceInLamports: bigint;\n title: string;\n description?: string;\n}\n","// Client-Side Payment Flow Helper\n// Headless payment flow for frontend integration (no Node.js dependencies)\n\nimport { TOKEN_MINTS, type PaymentAsset, type SolanaNetwork } from '../types';\n\n/**\n * Payment flow configuration\n */\nexport interface PaymentFlowConfig {\n /** Solana network */\n network: SolanaNetwork;\n /** Recipient wallet address */\n recipientWallet: string;\n /** Amount in smallest unit (lamports or token base units) */\n amount: bigint;\n /** Asset to pay with */\n asset?: PaymentAsset;\n /** Optional memo for the transaction */\n memo?: string;\n}\n\n/**\n * Solana Pay URL parameters\n */\nexport interface SolanaPayUrlParams {\n /** Recipient address */\n recipient: string;\n /** Amount in token's natural units (e.g., SOL, not lamports) */\n amount?: number;\n /** SPL token mint address */\n splToken?: string;\n /** Transaction reference */\n reference?: string;\n /** Label for the recipient */\n label?: string;\n /** Memo/message */\n message?: string;\n}\n\n/**\n * Build a Solana Pay URL for QR codes and deep linking\n * Compatible with Phantom, Solflare, and other Solana Pay wallets\n * \n * @example\n * ```typescript\n * const url = buildSolanaPayUrl({\n * recipient: 'CreatorWalletAddress',\n * amount: 0.01,\n * label: 'Article Unlock',\n * message: 'Premium Content Access',\n * });\n * // Returns: solana:CreatorWalletAddress?amount=0.01&label=Article%20Unlock&message=Premium%20Content%20Access\n * ```\n */\nexport function buildSolanaPayUrl(params: SolanaPayUrlParams): string {\n const { recipient, amount, splToken, reference, label, message } = params;\n\n const url = new URL(`solana:${recipient}`);\n\n if (amount !== undefined) {\n url.searchParams.set('amount', amount.toString());\n }\n\n if (splToken) {\n url.searchParams.set('spl-token', splToken);\n }\n\n if (reference) {\n url.searchParams.set('reference', reference);\n }\n\n if (label) {\n url.searchParams.set('label', label);\n }\n\n if (message) {\n url.searchParams.set('message', message);\n }\n\n return url.toString();\n}\n\n/**\n * Create a payment flow helper for frontend use\n * Provides utilities for building transactions and generating QR codes\n * \n * @example\n * ```typescript\n * const flow = createPaymentFlow({\n * network: 'devnet',\n * recipientWallet: 'CreatorAddress',\n * amount: 10000000n, // 0.01 SOL\n * });\n * \n * // Generate QR code URL\n * const qrUrl = flow.getSolanaPayUrl({ label: 'Unlock Article' });\n * \n * // Get transaction amount in natural units\n * const amountInSol = flow.getDisplayAmount();\n * ```\n */\nexport function createPaymentFlow(config: PaymentFlowConfig) {\n const { network, recipientWallet, amount, asset = 'native', memo } = config;\n\n // Determine decimals and mint\n let decimals = 9; // SOL default\n let mintAddress: string | undefined;\n\n if (asset === 'usdc') {\n decimals = 6;\n mintAddress = network === 'mainnet-beta' ? TOKEN_MINTS.USDC_MAINNET : TOKEN_MINTS.USDC_DEVNET;\n } else if (asset === 'usdt') {\n decimals = 6;\n mintAddress = TOKEN_MINTS.USDT_MAINNET;\n } else if (typeof asset === 'object' && 'mint' in asset) {\n decimals = asset.decimals ?? 6;\n mintAddress = asset.mint;\n }\n\n // Convert to natural units (from lamports/base units)\n const naturalAmount = Number(amount) / Math.pow(10, decimals);\n\n return {\n /** Get the payment configuration */\n getConfig: () => ({ ...config }),\n\n /** Get amount in natural display units (e.g., 0.01 SOL) */\n getDisplayAmount: () => naturalAmount,\n\n /** Get amount formatted with symbol */\n getFormattedAmount: () => {\n const symbol = asset === 'native' ? 'SOL'\n : asset === 'usdc' ? 'USDC'\n : asset === 'usdt' ? 'USDT'\n : 'tokens';\n return `${naturalAmount.toFixed(decimals > 6 ? 4 : 2)} ${symbol}`;\n },\n\n /** Generate Solana Pay URL for QR codes */\n getSolanaPayUrl: (options: { label?: string; reference?: string } = {}) => {\n return buildSolanaPayUrl({\n recipient: recipientWallet,\n amount: naturalAmount,\n splToken: mintAddress,\n label: options.label,\n reference: options.reference,\n message: memo,\n });\n },\n\n /** Get the token mint address (undefined for native SOL) */\n getMintAddress: () => mintAddress,\n\n /** Check if this is a native SOL payment */\n isNativePayment: () => asset === 'native',\n\n /** Get network information */\n getNetworkInfo: () => ({\n network,\n isMainnet: network === 'mainnet-beta',\n explorerUrl: network === 'mainnet-beta'\n ? 'https://explorer.solana.com'\n : 'https://explorer.solana.com?cluster=devnet',\n }),\n\n /** Build explorer URL for a transaction */\n getExplorerUrl: (signature: string) => {\n const baseUrl = 'https://explorer.solana.com/tx';\n const cluster = network === 'mainnet-beta' ? '' : '?cluster=devnet';\n return `${baseUrl}/${signature}${cluster}`;\n },\n };\n}\n\n/**\n * Create a unique reference for payment tracking\n * Uses crypto.randomUUID when available\n */\nexport function createPaymentReference(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // Fallback for environments without crypto.randomUUID\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n"]}
1
+ {"version":3,"sources":["../../src/client/types.ts","../../src/client/payment.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/** SPL Token asset specification */\nexport interface SPLTokenAsset {\n /** Token mint address */\n mint: string;\n /** Token decimals (default: 6 for USDC/USDT) */\n decimals?: number;\n}\n\n/** Asset types for payments */\nexport type PaymentAsset = 'native' | 'usdc' | 'usdt' | SPLTokenAsset;\n\nexport type SolanaNetwork = 'devnet' | 'mainnet-beta';\n\n/** Known SPL token mint addresses */\nexport const TOKEN_MINTS = {\n /** USDC on mainnet */\n USDC_MAINNET: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',\n /** USDC on devnet */\n USDC_DEVNET: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',\n /** USDT on mainnet */\n USDT_MAINNET: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',\n} as const;\n","// Client-Side Payment Flow Helper\n// Headless payment flow for frontend integration (no Node.js dependencies)\n\nimport { TOKEN_MINTS, type PaymentAsset, type SolanaNetwork } from './types';\n\n/**\n * Payment flow configuration\n */\nexport interface PaymentFlowConfig {\n /** Solana network */\n network: SolanaNetwork;\n /** Recipient wallet address */\n recipientWallet: string;\n /** Amount in smallest unit (lamports or token base units) */\n amount: bigint;\n /** Asset to pay with */\n asset?: PaymentAsset;\n /** Optional memo for the transaction */\n memo?: string;\n}\n\n/**\n * Solana Pay URL parameters\n */\nexport interface SolanaPayUrlParams {\n /** Recipient address */\n recipient: string;\n /** Amount in token's natural units (e.g., SOL, not lamports) */\n amount?: number;\n /** SPL token mint address */\n splToken?: string;\n /** Transaction reference */\n reference?: string;\n /** Label for the recipient */\n label?: string;\n /** Memo/message */\n message?: string;\n}\n\n/**\n * Build a Solana Pay URL for QR codes and deep linking\n * Compatible with Phantom, Solflare, and other Solana Pay wallets\n * \n * @example\n * ```typescript\n * const url = buildSolanaPayUrl({\n * recipient: 'CreatorWalletAddress',\n * amount: 0.01,\n * label: 'Article Unlock',\n * message: 'Premium Content Access',\n * });\n * // Returns: solana:CreatorWalletAddress?amount=0.01&label=Article%20Unlock&message=Premium%20Content%20Access\n * ```\n */\nexport function buildSolanaPayUrl(params: SolanaPayUrlParams): string {\n const { recipient, amount, splToken, reference, label, message } = params;\n\n const url = new URL(`solana:${recipient}`);\n\n if (amount !== undefined) {\n url.searchParams.set('amount', amount.toString());\n }\n\n if (splToken) {\n url.searchParams.set('spl-token', splToken);\n }\n\n if (reference) {\n url.searchParams.set('reference', reference);\n }\n\n if (label) {\n url.searchParams.set('label', label);\n }\n\n if (message) {\n url.searchParams.set('message', message);\n }\n\n return url.toString();\n}\n\n/**\n * Create a payment flow helper for frontend use\n * Provides utilities for building transactions and generating QR codes\n * \n * @example\n * ```typescript\n * const flow = createPaymentFlow({\n * network: 'devnet',\n * recipientWallet: 'CreatorAddress',\n * amount: 10000000n, // 0.01 SOL\n * });\n * \n * // Generate QR code URL\n * const qrUrl = flow.getSolanaPayUrl({ label: 'Unlock Article' });\n * \n * // Get transaction amount in natural units\n * const amountInSol = flow.getDisplayAmount();\n * ```\n */\nexport function createPaymentFlow(config: PaymentFlowConfig) {\n const { network, recipientWallet, amount, asset = 'native', memo } = config;\n\n // Determine decimals and mint\n let decimals = 9; // SOL default\n let mintAddress: string | undefined;\n\n if (asset === 'usdc') {\n decimals = 6;\n mintAddress = network === 'mainnet-beta' ? TOKEN_MINTS.USDC_MAINNET : TOKEN_MINTS.USDC_DEVNET;\n } else if (asset === 'usdt') {\n decimals = 6;\n mintAddress = TOKEN_MINTS.USDT_MAINNET;\n } else if (typeof asset === 'object' && 'mint' in asset) {\n decimals = asset.decimals ?? 6;\n mintAddress = asset.mint;\n }\n\n // Convert to natural units (from lamports/base units)\n const naturalAmount = Number(amount) / Math.pow(10, decimals);\n\n return {\n /** Get the payment configuration */\n getConfig: () => ({ ...config }),\n\n /** Get amount in natural display units (e.g., 0.01 SOL) */\n getDisplayAmount: () => naturalAmount,\n\n /** Get amount formatted with symbol */\n getFormattedAmount: () => {\n const symbol = asset === 'native' ? 'SOL'\n : asset === 'usdc' ? 'USDC'\n : asset === 'usdt' ? 'USDT'\n : 'tokens';\n return `${naturalAmount.toFixed(decimals > 6 ? 4 : 2)} ${symbol}`;\n },\n\n /** Generate Solana Pay URL for QR codes */\n getSolanaPayUrl: (options: { label?: string; reference?: string } = {}) => {\n return buildSolanaPayUrl({\n recipient: recipientWallet,\n amount: naturalAmount,\n splToken: mintAddress,\n label: options.label,\n reference: options.reference,\n message: memo,\n });\n },\n\n /** Get the token mint address (undefined for native SOL) */\n getMintAddress: () => mintAddress,\n\n /** Check if this is a native SOL payment */\n isNativePayment: () => asset === 'native',\n\n /** Get network information */\n getNetworkInfo: () => ({\n network,\n isMainnet: network === 'mainnet-beta',\n explorerUrl: network === 'mainnet-beta'\n ? 'https://explorer.solana.com'\n : 'https://explorer.solana.com?cluster=devnet',\n }),\n\n /** Build explorer URL for a transaction */\n getExplorerUrl: (signature: string) => {\n const baseUrl = 'https://explorer.solana.com/tx';\n const cluster = network === 'mainnet-beta' ? '' : '?cluster=devnet';\n return `${baseUrl}/${signature}${cluster}`;\n },\n };\n}\n\n/**\n * Create a unique reference for payment tracking\n * Uses crypto.randomUUID when available\n */\nexport function createPaymentReference(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n // Fallback for environments without crypto.randomUUID\n return `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n"]}