@alleyboss/micropay-solana-x402-paywall 3.0.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/index.cjs +2 -4
- package/dist/agent/index.js +2 -4
- package/dist/client/index.cjs +0 -2
- package/dist/client/index.js +0 -2
- package/dist/express/index.cjs +0 -2
- package/dist/express/index.js +0 -2
- package/dist/index.cjs +2 -4
- package/dist/index.js +2 -4
- package/dist/pricing/index.cjs +0 -2
- package/dist/pricing/index.js +0 -2
- package/dist/session/index.cjs +2 -4
- package/dist/session/index.js +2 -4
- package/package.json +2 -3
- package/dist/agent/index.cjs.map +0 -1
- package/dist/agent/index.js.map +0 -1
- package/dist/client/index.cjs.map +0 -1
- package/dist/client/index.js.map +0 -1
- package/dist/express/index.cjs.map +0 -1
- package/dist/express/index.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/pricing/index.cjs.map +0 -1
- package/dist/pricing/index.js.map +0 -1
- package/dist/session/index.cjs.map +0 -1
- package/dist/session/index.js.map +0 -1
package/dist/agent/index.cjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
var web3_js = require('@solana/web3.js');
|
|
4
4
|
var jose = require('jose');
|
|
5
|
-
var uuid = require('uuid');
|
|
6
5
|
|
|
7
6
|
// src/agent/agentPayment.ts
|
|
8
7
|
var DEFAULT_COMPUTE_UNITS = 2e5;
|
|
@@ -174,6 +173,7 @@ function generateAgentKeypair() {
|
|
|
174
173
|
publicKey: keypair.publicKey.toBase58()
|
|
175
174
|
};
|
|
176
175
|
}
|
|
176
|
+
var uuidv4 = () => crypto.randomUUID();
|
|
177
177
|
var MAX_CREDITS = 1e3;
|
|
178
178
|
var MIN_SECRET_LENGTH = 32;
|
|
179
179
|
function getSecretKey(secret) {
|
|
@@ -200,7 +200,7 @@ async function createCreditSession(walletAddress, purchaseId, config) {
|
|
|
200
200
|
if (!config.durationHours || config.durationHours <= 0 || config.durationHours > 8760) {
|
|
201
201
|
throw new Error("Session duration must be between 1 and 8760 hours (1 year)");
|
|
202
202
|
}
|
|
203
|
-
const sessionId =
|
|
203
|
+
const sessionId = uuidv4();
|
|
204
204
|
const now = Math.floor(Date.now() / 1e3);
|
|
205
205
|
const expiresAt = now + config.durationHours * 3600;
|
|
206
206
|
const bundleExpiry = config.bundleExpiryHours ? now + config.bundleExpiryHours * 3600 : expiresAt;
|
|
@@ -354,5 +354,3 @@ exports.hasAgentSufficientBalance = hasAgentSufficientBalance;
|
|
|
354
354
|
exports.keypairFromBase58 = keypairFromBase58;
|
|
355
355
|
exports.useCredit = useCredit;
|
|
356
356
|
exports.validateCreditSession = validateCreditSession;
|
|
357
|
-
//# sourceMappingURL=index.cjs.map
|
|
358
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/agent/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { PublicKey, SystemProgram, LAMPORTS_PER_SOL, Keypair, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } from '@solana/web3.js';
|
|
2
2
|
import { SignJWT, jwtVerify } from 'jose';
|
|
3
|
-
import { v4 } from 'uuid';
|
|
4
3
|
|
|
5
4
|
// src/agent/agentPayment.ts
|
|
6
5
|
var DEFAULT_COMPUTE_UNITS = 2e5;
|
|
@@ -172,6 +171,7 @@ function generateAgentKeypair() {
|
|
|
172
171
|
publicKey: keypair.publicKey.toBase58()
|
|
173
172
|
};
|
|
174
173
|
}
|
|
174
|
+
var uuidv4 = () => crypto.randomUUID();
|
|
175
175
|
var MAX_CREDITS = 1e3;
|
|
176
176
|
var MIN_SECRET_LENGTH = 32;
|
|
177
177
|
function getSecretKey(secret) {
|
|
@@ -198,7 +198,7 @@ async function createCreditSession(walletAddress, purchaseId, config) {
|
|
|
198
198
|
if (!config.durationHours || config.durationHours <= 0 || config.durationHours > 8760) {
|
|
199
199
|
throw new Error("Session duration must be between 1 and 8760 hours (1 year)");
|
|
200
200
|
}
|
|
201
|
-
const sessionId =
|
|
201
|
+
const sessionId = uuidv4();
|
|
202
202
|
const now = Math.floor(Date.now() / 1e3);
|
|
203
203
|
const expiresAt = now + config.durationHours * 3600;
|
|
204
204
|
const bundleExpiry = config.bundleExpiryHours ? now + config.bundleExpiryHours * 3600 : expiresAt;
|
|
@@ -343,5 +343,3 @@ async function getRemainingCredits(token, secret) {
|
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
export { addCredits, createCreditSession, executeAgentPayment, generateAgentKeypair, getAgentBalance, getRemainingCredits, hasAgentSufficientBalance, keypairFromBase58, useCredit, validateCreditSession };
|
|
346
|
-
//# sourceMappingURL=index.js.map
|
|
347
|
-
//# sourceMappingURL=index.js.map
|
package/dist/client/index.cjs
CHANGED
|
@@ -95,5 +95,3 @@ function createPaymentReference() {
|
|
|
95
95
|
exports.buildSolanaPayUrl = buildSolanaPayUrl;
|
|
96
96
|
exports.createPaymentFlow = createPaymentFlow;
|
|
97
97
|
exports.createPaymentReference = createPaymentReference;
|
|
98
|
-
//# sourceMappingURL=index.cjs.map
|
|
99
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/client/index.js
CHANGED
package/dist/express/index.cjs
CHANGED
package/dist/express/index.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -6,7 +6,6 @@ var client = require('@x402/core/client');
|
|
|
6
6
|
var svm = require('@x402/svm');
|
|
7
7
|
var web3_js = require('@solana/web3.js');
|
|
8
8
|
var jose = require('jose');
|
|
9
|
-
var uuid = require('uuid');
|
|
10
9
|
|
|
11
10
|
// src/index.ts
|
|
12
11
|
|
|
@@ -270,6 +269,7 @@ function generateAgentKeypair() {
|
|
|
270
269
|
publicKey: keypair.publicKey.toBase58()
|
|
271
270
|
};
|
|
272
271
|
}
|
|
272
|
+
var uuidv4 = () => crypto.randomUUID();
|
|
273
273
|
var MAX_CREDITS = 1e3;
|
|
274
274
|
var MIN_SECRET_LENGTH = 32;
|
|
275
275
|
function getSecretKey(secret) {
|
|
@@ -296,7 +296,7 @@ async function createCreditSession(walletAddress, purchaseId, config2) {
|
|
|
296
296
|
if (!config2.durationHours || config2.durationHours <= 0 || config2.durationHours > 8760) {
|
|
297
297
|
throw new Error("Session duration must be between 1 and 8760 hours (1 year)");
|
|
298
298
|
}
|
|
299
|
-
const sessionId =
|
|
299
|
+
const sessionId = uuidv4();
|
|
300
300
|
const now = Math.floor(Date.now() / 1e3);
|
|
301
301
|
const expiresAt = now + config2.durationHours * 3600;
|
|
302
302
|
const bundleExpiry = config2.bundleExpiryHours ? now + config2.bundleExpiryHours * 3600 : expiresAt;
|
|
@@ -615,5 +615,3 @@ Object.keys(svm).forEach(function (k) {
|
|
|
615
615
|
get: function () { return svm[k]; }
|
|
616
616
|
});
|
|
617
617
|
});
|
|
618
|
-
//# sourceMappingURL=index.cjs.map
|
|
619
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,6 @@ export * from '@x402/core/client';
|
|
|
4
4
|
export * from '@x402/svm';
|
|
5
5
|
import { PublicKey, SystemProgram, LAMPORTS_PER_SOL, Keypair, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } from '@solana/web3.js';
|
|
6
6
|
import { SignJWT, jwtVerify } from 'jose';
|
|
7
|
-
import { v4 } from 'uuid';
|
|
8
7
|
|
|
9
8
|
// src/index.ts
|
|
10
9
|
|
|
@@ -268,6 +267,7 @@ function generateAgentKeypair() {
|
|
|
268
267
|
publicKey: keypair.publicKey.toBase58()
|
|
269
268
|
};
|
|
270
269
|
}
|
|
270
|
+
var uuidv4 = () => crypto.randomUUID();
|
|
271
271
|
var MAX_CREDITS = 1e3;
|
|
272
272
|
var MIN_SECRET_LENGTH = 32;
|
|
273
273
|
function getSecretKey(secret) {
|
|
@@ -294,7 +294,7 @@ async function createCreditSession(walletAddress, purchaseId, config2) {
|
|
|
294
294
|
if (!config2.durationHours || config2.durationHours <= 0 || config2.durationHours > 8760) {
|
|
295
295
|
throw new Error("Session duration must be between 1 and 8760 hours (1 year)");
|
|
296
296
|
}
|
|
297
|
-
const sessionId =
|
|
297
|
+
const sessionId = uuidv4();
|
|
298
298
|
const now = Math.floor(Date.now() / 1e3);
|
|
299
299
|
const expiresAt = now + config2.durationHours * 3600;
|
|
300
300
|
const bundleExpiry = config2.bundleExpiryHours ? now + config2.bundleExpiryHours * 3600 : expiresAt;
|
|
@@ -569,5 +569,3 @@ function getProviders() {
|
|
|
569
569
|
}
|
|
570
570
|
|
|
571
571
|
export { addCredits, buildSolanaPayUrl, clearPriceCache, configurePricing, createCreditSession, createPaymentFlow, createPaymentReference, executeAgentPayment, formatPriceDisplay, formatPriceSync, generateAgentKeypair, getAgentBalance, getProviders, getRemainingCredits, getSolPrice, hasAgentSufficientBalance, keypairFromBase58, lamportsToUsd, usdToLamports, useCredit, validateCreditSession };
|
|
572
|
-
//# sourceMappingURL=index.js.map
|
|
573
|
-
//# sourceMappingURL=index.js.map
|
package/dist/pricing/index.cjs
CHANGED
package/dist/pricing/index.js
CHANGED
package/dist/session/index.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jose = require('jose');
|
|
4
|
-
var uuid = require('uuid');
|
|
5
4
|
|
|
6
5
|
// src/session/core.ts
|
|
6
|
+
var uuidv4 = () => crypto.randomUUID();
|
|
7
7
|
var MAX_ARTICLES_PER_SESSION = 100;
|
|
8
8
|
var MIN_SECRET_LENGTH = 32;
|
|
9
9
|
function getSecretKey(secret) {
|
|
@@ -36,7 +36,7 @@ async function createSession(walletAddress, articleId, config, siteWide = false)
|
|
|
36
36
|
if (!config.durationHours || config.durationHours <= 0 || config.durationHours > 720) {
|
|
37
37
|
throw new Error("Session duration must be between 1 and 720 hours");
|
|
38
38
|
}
|
|
39
|
-
const sessionId =
|
|
39
|
+
const sessionId = uuidv4();
|
|
40
40
|
const now = Math.floor(Date.now() / 1e3);
|
|
41
41
|
const expiresAt = now + config.durationHours * 3600;
|
|
42
42
|
const session = {
|
|
@@ -136,5 +136,3 @@ exports.addArticleToSession = addArticleToSession;
|
|
|
136
136
|
exports.createSession = createSession;
|
|
137
137
|
exports.isArticleUnlocked = isArticleUnlocked;
|
|
138
138
|
exports.validateSession = validateSession;
|
|
139
|
-
//# sourceMappingURL=index.cjs.map
|
|
140
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/session/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SignJWT, jwtVerify } from 'jose';
|
|
2
|
-
import { v4 } from 'uuid';
|
|
3
2
|
|
|
4
3
|
// src/session/core.ts
|
|
4
|
+
var uuidv4 = () => crypto.randomUUID();
|
|
5
5
|
var MAX_ARTICLES_PER_SESSION = 100;
|
|
6
6
|
var MIN_SECRET_LENGTH = 32;
|
|
7
7
|
function getSecretKey(secret) {
|
|
@@ -34,7 +34,7 @@ async function createSession(walletAddress, articleId, config, siteWide = false)
|
|
|
34
34
|
if (!config.durationHours || config.durationHours <= 0 || config.durationHours > 720) {
|
|
35
35
|
throw new Error("Session duration must be between 1 and 720 hours");
|
|
36
36
|
}
|
|
37
|
-
const sessionId =
|
|
37
|
+
const sessionId = uuidv4();
|
|
38
38
|
const now = Math.floor(Date.now() / 1e3);
|
|
39
39
|
const expiresAt = now + config.durationHours * 3600;
|
|
40
40
|
const session = {
|
|
@@ -131,5 +131,3 @@ async function isArticleUnlocked(token, articleId, secret) {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
export { addArticleToSession, createSession, isArticleUnlocked, validateSession };
|
|
134
|
-
//# sourceMappingURL=index.js.map
|
|
135
|
-
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alleyboss/micropay-solana-x402-paywall",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "Production-ready Solana micropayments library wrapper for official x402 SDK",
|
|
5
5
|
"author": "AlleyBoss",
|
|
6
6
|
"license": "MIT",
|
|
@@ -100,8 +100,7 @@
|
|
|
100
100
|
"dependencies": {
|
|
101
101
|
"@x402/core": "^2.1.0",
|
|
102
102
|
"@x402/svm": "^2.1.0",
|
|
103
|
-
"jose": "^6.1.3"
|
|
104
|
-
"uuid": "^13.0.0"
|
|
103
|
+
"jose": "^6.1.3"
|
|
105
104
|
},
|
|
106
105
|
"peerDependencies": {
|
|
107
106
|
"@solana/web3.js": "^1.90.0"
|
package/dist/agent/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/agent/solanaHelpers.ts","../../src/agent/agentPayment.ts","../../src/agent/credits.ts"],"names":["ComputeBudgetProgram","TransactionMessage","VersionedTransaction","PublicKey","SystemProgram","LAMPORTS_PER_SOL","Keypair","uuidv4","SignJWT","jwtVerify"],"mappings":"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","file":"index.cjs","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"]}
|
package/dist/agent/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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"]}
|
package/dist/client/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/express/index.ts"],"names":["server","x402HTTPResourceServer"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Request, Response, NextFunction } from 'express';\nimport {\n x402ResourceServer,\n x402HTTPResourceServer,\n type HTTPAdapter,\n type RouteConfig\n} from '@x402/core/server';\n\n/**\n * Express Adapter for x402\n */\nexport class ExpressAdapter implements HTTPAdapter {\n constructor(private req: Request) { }\n\n getHeader(name: string): string | undefined {\n const val = this.req.headers[name.toLowerCase()];\n if (Array.isArray(val)) return val[0];\n return val;\n }\n\n getMethod(): string {\n return this.req.method;\n }\n\n getPath(): string {\n return this.req.path;\n }\n\n getUrl(): string {\n return this.req.originalUrl || this.req.url;\n }\n\n getAcceptHeader(): string {\n return this.req.headers['accept'] || '';\n }\n\n getUserAgent(): string {\n return this.req.headers['user-agent'] || '';\n }\n\n getQueryParams(): Record<string, string | string[]> {\n return this.req.query as Record<string, string | string[]>;\n }\n\n getQueryParam(name: string): string | string[] | undefined {\n return this.req.query[name] as string | string[] | undefined;\n }\n\n async getBody(): Promise<unknown> {\n return this.req.body;\n }\n}\n\n/**\n * Create x402 middleware for Express\n * \n * @example\n * ```typescript\n * import { x402ResourceServer } from '@x402/core/server';\n * import { x402Middleware } from '@alleyboss/micropay-solana-x402-paywall/express';\n * \n * const server = new x402ResourceServer(facilitatorClient);\n * \n * app.get('/premium', x402Middleware(server, {\n * accepts: { scheme: 'exact', ... },\n * description: 'Premium content'\n * }), (req, res) => {\n * res.send('You paid!');\n * });\n * ```\n */\nexport function x402Middleware(\n server: x402ResourceServer,\n routeConfig: RouteConfig\n) {\n return async (req: Request, res: Response, next: NextFunction) => {\n try {\n // Create a temporary HTTP resource server for this request\n // We use the current path + method to ensure it matches\n // NOTE: req.path contains the actual path (e.g. /users/123), not the route pattern\n const currentRouteKey = `${req.method} ${req.path}`;\n const routes = {\n [currentRouteKey]: routeConfig\n };\n\n const httpServer = new x402HTTPResourceServer(server, routes);\n await httpServer.initialize();\n\n const adapter = new ExpressAdapter(req);\n\n // Process request\n const result = await httpServer.processHTTPRequest({\n adapter,\n method: req.method,\n path: req.path\n });\n\n if (result.type === 'payment-verified' || result.type === 'no-payment-required') {\n // Attach result to request\n (req as any).x402 = result;\n return next();\n }\n\n if (result.type === 'payment-error') {\n const instructions = result.response;\n\n // Set headers\n if (instructions.headers) {\n Object.entries(instructions.headers).forEach(([key, value]) => {\n if (value) res.setHeader(key, value);\n });\n }\n\n // Send response\n res.status(instructions.status).send(instructions.body);\n return;\n }\n\n } catch (error) {\n console.error('x402 middleware error:', error);\n res.status(500).json({ error: 'Payment verification error' });\n }\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/express/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { Request, Response, NextFunction } from 'express';\nimport {\n x402ResourceServer,\n x402HTTPResourceServer,\n type HTTPAdapter,\n type RouteConfig\n} from '@x402/core/server';\n\n/**\n * Express Adapter for x402\n */\nexport class ExpressAdapter implements HTTPAdapter {\n constructor(private req: Request) { }\n\n getHeader(name: string): string | undefined {\n const val = this.req.headers[name.toLowerCase()];\n if (Array.isArray(val)) return val[0];\n return val;\n }\n\n getMethod(): string {\n return this.req.method;\n }\n\n getPath(): string {\n return this.req.path;\n }\n\n getUrl(): string {\n return this.req.originalUrl || this.req.url;\n }\n\n getAcceptHeader(): string {\n return this.req.headers['accept'] || '';\n }\n\n getUserAgent(): string {\n return this.req.headers['user-agent'] || '';\n }\n\n getQueryParams(): Record<string, string | string[]> {\n return this.req.query as Record<string, string | string[]>;\n }\n\n getQueryParam(name: string): string | string[] | undefined {\n return this.req.query[name] as string | string[] | undefined;\n }\n\n async getBody(): Promise<unknown> {\n return this.req.body;\n }\n}\n\n/**\n * Create x402 middleware for Express\n * \n * @example\n * ```typescript\n * import { x402ResourceServer } from '@x402/core/server';\n * import { x402Middleware } from '@alleyboss/micropay-solana-x402-paywall/express';\n * \n * const server = new x402ResourceServer(facilitatorClient);\n * \n * app.get('/premium', x402Middleware(server, {\n * accepts: { scheme: 'exact', ... },\n * description: 'Premium content'\n * }), (req, res) => {\n * res.send('You paid!');\n * });\n * ```\n */\nexport function x402Middleware(\n server: x402ResourceServer,\n routeConfig: RouteConfig\n) {\n return async (req: Request, res: Response, next: NextFunction) => {\n try {\n // Create a temporary HTTP resource server for this request\n // We use the current path + method to ensure it matches\n // NOTE: req.path contains the actual path (e.g. /users/123), not the route pattern\n const currentRouteKey = `${req.method} ${req.path}`;\n const routes = {\n [currentRouteKey]: routeConfig\n };\n\n const httpServer = new x402HTTPResourceServer(server, routes);\n await httpServer.initialize();\n\n const adapter = new ExpressAdapter(req);\n\n // Process request\n const result = await httpServer.processHTTPRequest({\n adapter,\n method: req.method,\n path: req.path\n });\n\n if (result.type === 'payment-verified' || result.type === 'no-payment-required') {\n // Attach result to request\n (req as any).x402 = result;\n return next();\n }\n\n if (result.type === 'payment-error') {\n const instructions = result.response;\n\n // Set headers\n if (instructions.headers) {\n Object.entries(instructions.headers).forEach(([key, value]) => {\n if (value) res.setHeader(key, value);\n });\n }\n\n // Send response\n res.status(instructions.status).send(instructions.body);\n return;\n }\n\n } catch (error) {\n console.error('x402 middleware error:', error);\n res.status(500).json({ error: 'Payment verification error' });\n }\n };\n}\n"]}
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/types.ts","../src/client/payment.ts","../src/agent/solanaHelpers.ts","../src/agent/agentPayment.ts","../src/agent/credits.ts","../src/pricing/index.ts"],"names":["config","ComputeBudgetProgram","TransactionMessage","VersionedTransaction","PublicKey","SystemProgram","LAMPORTS_PER_SOL","Keypair","uuidv4","SignJWT","jwtVerify"],"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","// 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","// Price Conversion Helpers\n// Multi-provider SOL price fetching with fallback rotation\n\n/**\n * Price data from API\n */\nexport interface PriceData {\n /** SOL price in USD */\n solPrice: number;\n /** Timestamp of price fetch */\n fetchedAt: Date;\n /** Source of price data */\n source: string;\n}\n\n/**\n * Custom price provider function type\n */\nexport type CustomPriceProvider = () => Promise<number>;\n\n/**\n * Price provider configuration\n */\nexport interface PriceConfig {\n /** Custom price provider (if set, skips built-in providers) */\n customProvider?: CustomPriceProvider;\n /** Cache TTL in milliseconds (default: 60000) */\n cacheTTL?: number;\n /** Request timeout in milliseconds (default: 5000) */\n timeout?: number;\n}\n\n// Cached price data\nlet cachedPrice: PriceData | null = null;\nlet config: PriceConfig = {};\nlet lastProviderIndex = -1;\n\n/**\n * Configure price fetching\n * \n * @example\n * ```typescript\n * // Use custom API\n * configurePricing({\n * customProvider: async () => {\n * const res = await fetch('https://my-api.com/sol-price');\n * return (await res.json()).price;\n * },\n * });\n * \n * // Or just adjust cache TTL\n * configurePricing({ cacheTTL: 30000 }); // 30 seconds\n * ```\n */\nexport function configurePricing(newConfig: PriceConfig): void {\n config = { ...config, ...newConfig };\n cachedPrice = null; // Clear cache on config change\n}\n\n/**\n * Built-in price providers with reliability rotation\n */\nconst PROVIDERS = [\n {\n name: 'coincap',\n url: 'https://api.coincap.io/v2/assets/solana',\n parse: (data: { data?: { priceUsd?: string } }) => parseFloat(data.data?.priceUsd || '0'),\n },\n {\n name: 'binance',\n url: 'https://api.binance.com/api/v3/ticker/price?symbol=SOLUSDT',\n parse: (data: { price?: string }) => parseFloat(data.price || '0'),\n },\n {\n name: 'coingecko',\n url: 'https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd',\n parse: (data: { solana?: { usd?: number } }) => data.solana?.usd || 0,\n },\n {\n name: 'kraken',\n url: 'https://api.kraken.com/0/public/Ticker?pair=SOLUSD',\n parse: (data: { result?: { SOLUSD?: { c?: string[] } } }) =>\n parseFloat(data.result?.SOLUSD?.c?.[0] || '0'),\n },\n];\n\n/**\n * Fetch price from a single provider\n */\nasync function fetchFromProvider(\n provider: typeof PROVIDERS[0],\n timeout: number\n): Promise<number> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(provider.url, {\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const data = await response.json() as Record<string, unknown>;\n const price = provider.parse(data as Parameters<typeof provider.parse>[0]);\n\n if (!price || price <= 0) {\n throw new Error('Invalid price');\n }\n\n return price;\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\n/**\n * Get SOL price with multi-provider fallback\n * \n * Provider rotation order:\n * 1. CoinCap (primary)\n * 2. Binance (backup #1)\n * 3. CoinGecko (backup #2)\n * 4. Kraken (backup #3)\n * \n * @example\n * ```typescript\n * const { solPrice, source } = await getSolPrice();\n * console.log(`SOL is $${solPrice} (from ${source})`);\n * ```\n */\nexport async function getSolPrice(): Promise<PriceData> {\n const cacheTTL = config.cacheTTL ?? 60000;\n const timeout = config.timeout ?? 5000;\n\n // Return cached price if valid\n if (cachedPrice && Date.now() - cachedPrice.fetchedAt.getTime() < cacheTTL) {\n return cachedPrice;\n }\n\n // Try custom provider first if configured\n if (config.customProvider) {\n try {\n const price = await config.customProvider();\n if (price > 0) {\n cachedPrice = {\n solPrice: price,\n fetchedAt: new Date(),\n source: 'custom',\n };\n return cachedPrice;\n }\n } catch {\n // Fall through to built-in providers\n }\n }\n\n // Try providers in rotation, starting after the last successful one\n for (let i = 0; i < PROVIDERS.length; i++) {\n const idx = (lastProviderIndex + 1 + i) % PROVIDERS.length;\n const provider = PROVIDERS[idx];\n\n try {\n const price = await fetchFromProvider(provider, timeout);\n lastProviderIndex = idx;\n\n cachedPrice = {\n solPrice: price,\n fetchedAt: new Date(),\n source: provider.name,\n };\n return cachedPrice;\n } catch {\n // Try next provider\n continue;\n }\n }\n\n // All providers failed, use stale cache if available\n if (cachedPrice) {\n // Mark as stale but still usable\n return {\n ...cachedPrice,\n source: `${cachedPrice.source} (stale)`,\n };\n }\n\n // SECURITY: Never use hardcoded fallback - throw error instead\n throw new Error(\n 'Failed to fetch SOL price from all providers. ' +\n 'Configure a custom provider or ensure network connectivity.'\n );\n}\n\n/**\n * Convert lamports to USD\n * \n * @example\n * ```typescript\n * const usd = await lamportsToUsd(10_000_000n); // 0.01 SOL\n * console.log(`$${usd.toFixed(2)}`);\n * ```\n */\nexport async function lamportsToUsd(lamports: bigint): Promise<number> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000;\n return sol * solPrice;\n}\n\n/**\n * Convert USD to lamports\n * \n * @example\n * ```typescript\n * const lamports = await usdToLamports(1.50); // $1.50\n * console.log(`${lamports} lamports`);\n * ```\n */\nexport async function usdToLamports(usd: number): Promise<bigint> {\n const { solPrice } = await getSolPrice();\n const sol = usd / solPrice;\n return BigInt(Math.floor(sol * 1_000_000_000));\n}\n\n/**\n * Format a price for display with both SOL and USD\n * \n * @example\n * ```typescript\n * const display = await formatPriceDisplay(10_000_000n);\n * // Returns: \"0.0100 SOL (~$1.50)\"\n * ```\n */\nexport async function formatPriceDisplay(lamports: bigint): Promise<string> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`;\n}\n\n/**\n * Synchronous price formatting (requires pre-fetched price)\n */\nexport function formatPriceSync(lamports: bigint, solPrice: number): {\n sol: number;\n usd: number;\n formatted: string;\n} {\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return {\n sol,\n usd,\n formatted: `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`,\n };\n}\n\n/**\n * Clear the price cache (for testing or manual refresh)\n */\nexport function clearPriceCache(): void {\n cachedPrice = null;\n lastProviderIndex = -1;\n}\n\n/**\n * Get list of available built-in providers\n */\nexport function getProviders(): { name: string; url: string }[] {\n return PROVIDERS.map(p => ({ name: p.name, url: p.url }));\n}\n"]}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/types.ts","../src/client/payment.ts","../src/agent/solanaHelpers.ts","../src/agent/agentPayment.ts","../src/agent/credits.ts","../src/pricing/index.ts"],"names":["config","PublicKey","uuidv4"],"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","// 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","// Price Conversion Helpers\n// Multi-provider SOL price fetching with fallback rotation\n\n/**\n * Price data from API\n */\nexport interface PriceData {\n /** SOL price in USD */\n solPrice: number;\n /** Timestamp of price fetch */\n fetchedAt: Date;\n /** Source of price data */\n source: string;\n}\n\n/**\n * Custom price provider function type\n */\nexport type CustomPriceProvider = () => Promise<number>;\n\n/**\n * Price provider configuration\n */\nexport interface PriceConfig {\n /** Custom price provider (if set, skips built-in providers) */\n customProvider?: CustomPriceProvider;\n /** Cache TTL in milliseconds (default: 60000) */\n cacheTTL?: number;\n /** Request timeout in milliseconds (default: 5000) */\n timeout?: number;\n}\n\n// Cached price data\nlet cachedPrice: PriceData | null = null;\nlet config: PriceConfig = {};\nlet lastProviderIndex = -1;\n\n/**\n * Configure price fetching\n * \n * @example\n * ```typescript\n * // Use custom API\n * configurePricing({\n * customProvider: async () => {\n * const res = await fetch('https://my-api.com/sol-price');\n * return (await res.json()).price;\n * },\n * });\n * \n * // Or just adjust cache TTL\n * configurePricing({ cacheTTL: 30000 }); // 30 seconds\n * ```\n */\nexport function configurePricing(newConfig: PriceConfig): void {\n config = { ...config, ...newConfig };\n cachedPrice = null; // Clear cache on config change\n}\n\n/**\n * Built-in price providers with reliability rotation\n */\nconst PROVIDERS = [\n {\n name: 'coincap',\n url: 'https://api.coincap.io/v2/assets/solana',\n parse: (data: { data?: { priceUsd?: string } }) => parseFloat(data.data?.priceUsd || '0'),\n },\n {\n name: 'binance',\n url: 'https://api.binance.com/api/v3/ticker/price?symbol=SOLUSDT',\n parse: (data: { price?: string }) => parseFloat(data.price || '0'),\n },\n {\n name: 'coingecko',\n url: 'https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd',\n parse: (data: { solana?: { usd?: number } }) => data.solana?.usd || 0,\n },\n {\n name: 'kraken',\n url: 'https://api.kraken.com/0/public/Ticker?pair=SOLUSD',\n parse: (data: { result?: { SOLUSD?: { c?: string[] } } }) =>\n parseFloat(data.result?.SOLUSD?.c?.[0] || '0'),\n },\n];\n\n/**\n * Fetch price from a single provider\n */\nasync function fetchFromProvider(\n provider: typeof PROVIDERS[0],\n timeout: number\n): Promise<number> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(provider.url, {\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const data = await response.json() as Record<string, unknown>;\n const price = provider.parse(data as Parameters<typeof provider.parse>[0]);\n\n if (!price || price <= 0) {\n throw new Error('Invalid price');\n }\n\n return price;\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\n/**\n * Get SOL price with multi-provider fallback\n * \n * Provider rotation order:\n * 1. CoinCap (primary)\n * 2. Binance (backup #1)\n * 3. CoinGecko (backup #2)\n * 4. Kraken (backup #3)\n * \n * @example\n * ```typescript\n * const { solPrice, source } = await getSolPrice();\n * console.log(`SOL is $${solPrice} (from ${source})`);\n * ```\n */\nexport async function getSolPrice(): Promise<PriceData> {\n const cacheTTL = config.cacheTTL ?? 60000;\n const timeout = config.timeout ?? 5000;\n\n // Return cached price if valid\n if (cachedPrice && Date.now() - cachedPrice.fetchedAt.getTime() < cacheTTL) {\n return cachedPrice;\n }\n\n // Try custom provider first if configured\n if (config.customProvider) {\n try {\n const price = await config.customProvider();\n if (price > 0) {\n cachedPrice = {\n solPrice: price,\n fetchedAt: new Date(),\n source: 'custom',\n };\n return cachedPrice;\n }\n } catch {\n // Fall through to built-in providers\n }\n }\n\n // Try providers in rotation, starting after the last successful one\n for (let i = 0; i < PROVIDERS.length; i++) {\n const idx = (lastProviderIndex + 1 + i) % PROVIDERS.length;\n const provider = PROVIDERS[idx];\n\n try {\n const price = await fetchFromProvider(provider, timeout);\n lastProviderIndex = idx;\n\n cachedPrice = {\n solPrice: price,\n fetchedAt: new Date(),\n source: provider.name,\n };\n return cachedPrice;\n } catch {\n // Try next provider\n continue;\n }\n }\n\n // All providers failed, use stale cache if available\n if (cachedPrice) {\n // Mark as stale but still usable\n return {\n ...cachedPrice,\n source: `${cachedPrice.source} (stale)`,\n };\n }\n\n // SECURITY: Never use hardcoded fallback - throw error instead\n throw new Error(\n 'Failed to fetch SOL price from all providers. ' +\n 'Configure a custom provider or ensure network connectivity.'\n );\n}\n\n/**\n * Convert lamports to USD\n * \n * @example\n * ```typescript\n * const usd = await lamportsToUsd(10_000_000n); // 0.01 SOL\n * console.log(`$${usd.toFixed(2)}`);\n * ```\n */\nexport async function lamportsToUsd(lamports: bigint): Promise<number> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000;\n return sol * solPrice;\n}\n\n/**\n * Convert USD to lamports\n * \n * @example\n * ```typescript\n * const lamports = await usdToLamports(1.50); // $1.50\n * console.log(`${lamports} lamports`);\n * ```\n */\nexport async function usdToLamports(usd: number): Promise<bigint> {\n const { solPrice } = await getSolPrice();\n const sol = usd / solPrice;\n return BigInt(Math.floor(sol * 1_000_000_000));\n}\n\n/**\n * Format a price for display with both SOL and USD\n * \n * @example\n * ```typescript\n * const display = await formatPriceDisplay(10_000_000n);\n * // Returns: \"0.0100 SOL (~$1.50)\"\n * ```\n */\nexport async function formatPriceDisplay(lamports: bigint): Promise<string> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`;\n}\n\n/**\n * Synchronous price formatting (requires pre-fetched price)\n */\nexport function formatPriceSync(lamports: bigint, solPrice: number): {\n sol: number;\n usd: number;\n formatted: string;\n} {\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return {\n sol,\n usd,\n formatted: `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`,\n };\n}\n\n/**\n * Clear the price cache (for testing or manual refresh)\n */\nexport function clearPriceCache(): void {\n cachedPrice = null;\n lastProviderIndex = -1;\n}\n\n/**\n * Get list of available built-in providers\n */\nexport function getProviders(): { name: string; url: string }[] {\n return PROVIDERS.map(p => ({ name: p.name, url: p.url }));\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/pricing/index.ts"],"names":[],"mappings":";;;AAiCA,IAAI,WAAA,GAAgC,IAAA;AACpC,IAAI,SAAsB,EAAC;AAC3B,IAAI,iBAAA,GAAoB,EAAA;AAmBjB,SAAS,iBAAiB,SAAA,EAA8B;AAC3D,EAAA,MAAA,GAAS,EAAE,GAAG,MAAA,EAAQ,GAAG,SAAA,EAAU;AACnC,EAAA,WAAA,GAAc,IAAA;AAClB;AAKA,IAAM,SAAA,GAAY;AAAA,EACd;AAAA,IACI,IAAA,EAAM,SAAA;AAAA,IACN,GAAA,EAAK,yCAAA;AAAA,IACL,OAAO,CAAC,IAAA,KAA2C,WAAW,IAAA,CAAK,IAAA,EAAM,YAAY,GAAG;AAAA,GAC5F;AAAA,EACA;AAAA,IACI,IAAA,EAAM,SAAA;AAAA,IACN,GAAA,EAAK,4DAAA;AAAA,IACL,OAAO,CAAC,IAAA,KAA6B,UAAA,CAAW,IAAA,CAAK,SAAS,GAAG;AAAA,GACrE;AAAA,EACA;AAAA,IACI,IAAA,EAAM,WAAA;AAAA,IACN,GAAA,EAAK,4EAAA;AAAA,IACL,KAAA,EAAO,CAAC,IAAA,KAAwC,IAAA,CAAK,QAAQ,GAAA,IAAO;AAAA,GACxE;AAAA,EACA;AAAA,IACI,IAAA,EAAM,QAAA;AAAA,IACN,GAAA,EAAK,oDAAA;AAAA,IACL,KAAA,EAAO,CAAC,IAAA,KACJ,UAAA,CAAW,IAAA,CAAK,QAAQ,MAAA,EAAQ,CAAA,GAAI,CAAC,CAAA,IAAK,GAAG;AAAA;AAEzD,CAAA;AAKA,eAAe,iBAAA,CACX,UACA,OAAA,EACe;AACf,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,YAAY,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,OAAO,CAAA;AAE9D,EAAA,IAAI;AACA,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,QAAA,CAAS,GAAA,EAAK;AAAA,MACvC,OAAA,EAAS,EAAE,QAAA,EAAU,kBAAA,EAAmB;AAAA,MACxC,QAAQ,UAAA,CAAW;AAAA,KACtB,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACd,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,IAC7C;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,IAA4C,CAAA;AAEzE,IAAA,IAAI,CAAC,KAAA,IAAS,KAAA,IAAS,CAAA,EAAG;AACtB,MAAA,MAAM,IAAI,MAAM,eAAe,CAAA;AAAA,IACnC;AAEA,IAAA,OAAO,KAAA;AAAA,EACX,CAAA,SAAE;AACE,IAAA,YAAA,CAAa,SAAS,CAAA;AAAA,EAC1B;AACJ;AAiBA,eAAsB,WAAA,GAAkC;AACpD,EAAA,MAAM,QAAA,GAAW,OAAO,QAAA,IAAY,GAAA;AACpC,EAAA,MAAM,OAAA,GAAU,OAAO,OAAA,IAAW,GAAA;AAGlC,EAAA,IAAI,WAAA,IAAe,KAAK,GAAA,EAAI,GAAI,YAAY,SAAA,CAAU,OAAA,KAAY,QAAA,EAAU;AACxE,IAAA,OAAO,WAAA;AAAA,EACX;AAGA,EAAA,IAAI,OAAO,cAAA,EAAgB;AACvB,IAAA,IAAI;AACA,MAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,cAAA,EAAe;AAC1C,MAAA,IAAI,QAAQ,CAAA,EAAG;AACX,QAAA,WAAA,GAAc;AAAA,UACV,QAAA,EAAU,KAAA;AAAA,UACV,SAAA,sBAAe,IAAA,EAAK;AAAA,UACpB,MAAA,EAAQ;AAAA,SACZ;AACA,QAAA,OAAO,WAAA;AAAA,MACX;AAAA,IACJ,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACJ;AAGA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,CAAU,QAAQ,CAAA,EAAA,EAAK;AACvC,IAAA,MAAM,GAAA,GAAA,CAAO,iBAAA,GAAoB,CAAA,GAAI,CAAA,IAAK,SAAA,CAAU,MAAA;AACpD,IAAA,MAAM,QAAA,GAAW,UAAU,GAAG,CAAA;AAE9B,IAAA,IAAI;AACA,MAAA,MAAM,KAAA,GAAQ,MAAM,iBAAA,CAAkB,QAAA,EAAU,OAAO,CAAA;AACvD,MAAA,iBAAA,GAAoB,GAAA;AAEpB,MAAA,WAAA,GAAc;AAAA,QACV,QAAA,EAAU,KAAA;AAAA,QACV,SAAA,sBAAe,IAAA,EAAK;AAAA,QACpB,QAAQ,QAAA,CAAS;AAAA,OACrB;AACA,MAAA,OAAO,WAAA;AAAA,IACX,CAAA,CAAA,MAAQ;AAEJ,MAAA;AAAA,IACJ;AAAA,EACJ;AAGA,EAAA,IAAI,WAAA,EAAa;AAEb,IAAA,OAAO;AAAA,MACH,GAAG,WAAA;AAAA,MACH,MAAA,EAAQ,CAAA,EAAG,WAAA,CAAY,MAAM,CAAA,QAAA;AAAA,KACjC;AAAA,EACJ;AAGA,EAAA,MAAM,IAAI,KAAA;AAAA,IACN;AAAA,GAEJ;AACJ;AAWA,eAAsB,cAAc,QAAA,EAAmC;AACnE,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,WAAA,EAAY;AACvC,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAQ,CAAA,GAAI,GAAA;AAC/B,EAAA,OAAO,GAAA,GAAM,QAAA;AACjB;AAWA,eAAsB,cAAc,GAAA,EAA8B;AAC9D,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,WAAA,EAAY;AACvC,EAAA,MAAM,MAAM,GAAA,GAAM,QAAA;AAClB,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,GAAa,CAAC,CAAA;AACjD;AAWA,eAAsB,mBAAmB,QAAA,EAAmC;AACxE,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,WAAA,EAAY;AACvC,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAQ,CAAA,GAAI,GAAA;AAC/B,EAAA,MAAM,MAAM,GAAA,GAAM,QAAA;AAElB,EAAA,OAAO,CAAA,EAAG,IAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,QAAA,EAAW,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA;AACrD;AAKO,SAAS,eAAA,CAAgB,UAAkB,QAAA,EAIhD;AACE,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,QAAQ,CAAA,GAAI,GAAA;AAC/B,EAAA,MAAM,MAAM,GAAA,GAAM,QAAA;AAElB,EAAA,OAAO;AAAA,IACH,GAAA;AAAA,IACA,GAAA;AAAA,IACA,SAAA,EAAW,CAAA,EAAG,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,QAAA,EAAW,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA;AAAA,GACzD;AACJ;AAKO,SAAS,eAAA,GAAwB;AACpC,EAAA,WAAA,GAAc,IAAA;AACd,EAAA,iBAAA,GAAoB,EAAA;AACxB;AAKO,SAAS,YAAA,GAAgD;AAC5D,EAAA,OAAO,SAAA,CAAU,GAAA,CAAI,CAAA,CAAA,MAAM,EAAE,IAAA,EAAM,EAAE,IAAA,EAAM,GAAA,EAAK,CAAA,CAAE,GAAA,EAAI,CAAE,CAAA;AAC5D","file":"index.cjs","sourcesContent":["// Price Conversion Helpers\n// Multi-provider SOL price fetching with fallback rotation\n\n/**\n * Price data from API\n */\nexport interface PriceData {\n /** SOL price in USD */\n solPrice: number;\n /** Timestamp of price fetch */\n fetchedAt: Date;\n /** Source of price data */\n source: string;\n}\n\n/**\n * Custom price provider function type\n */\nexport type CustomPriceProvider = () => Promise<number>;\n\n/**\n * Price provider configuration\n */\nexport interface PriceConfig {\n /** Custom price provider (if set, skips built-in providers) */\n customProvider?: CustomPriceProvider;\n /** Cache TTL in milliseconds (default: 60000) */\n cacheTTL?: number;\n /** Request timeout in milliseconds (default: 5000) */\n timeout?: number;\n}\n\n// Cached price data\nlet cachedPrice: PriceData | null = null;\nlet config: PriceConfig = {};\nlet lastProviderIndex = -1;\n\n/**\n * Configure price fetching\n * \n * @example\n * ```typescript\n * // Use custom API\n * configurePricing({\n * customProvider: async () => {\n * const res = await fetch('https://my-api.com/sol-price');\n * return (await res.json()).price;\n * },\n * });\n * \n * // Or just adjust cache TTL\n * configurePricing({ cacheTTL: 30000 }); // 30 seconds\n * ```\n */\nexport function configurePricing(newConfig: PriceConfig): void {\n config = { ...config, ...newConfig };\n cachedPrice = null; // Clear cache on config change\n}\n\n/**\n * Built-in price providers with reliability rotation\n */\nconst PROVIDERS = [\n {\n name: 'coincap',\n url: 'https://api.coincap.io/v2/assets/solana',\n parse: (data: { data?: { priceUsd?: string } }) => parseFloat(data.data?.priceUsd || '0'),\n },\n {\n name: 'binance',\n url: 'https://api.binance.com/api/v3/ticker/price?symbol=SOLUSDT',\n parse: (data: { price?: string }) => parseFloat(data.price || '0'),\n },\n {\n name: 'coingecko',\n url: 'https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd',\n parse: (data: { solana?: { usd?: number } }) => data.solana?.usd || 0,\n },\n {\n name: 'kraken',\n url: 'https://api.kraken.com/0/public/Ticker?pair=SOLUSD',\n parse: (data: { result?: { SOLUSD?: { c?: string[] } } }) =>\n parseFloat(data.result?.SOLUSD?.c?.[0] || '0'),\n },\n];\n\n/**\n * Fetch price from a single provider\n */\nasync function fetchFromProvider(\n provider: typeof PROVIDERS[0],\n timeout: number\n): Promise<number> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(provider.url, {\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const data = await response.json() as Record<string, unknown>;\n const price = provider.parse(data as Parameters<typeof provider.parse>[0]);\n\n if (!price || price <= 0) {\n throw new Error('Invalid price');\n }\n\n return price;\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\n/**\n * Get SOL price with multi-provider fallback\n * \n * Provider rotation order:\n * 1. CoinCap (primary)\n * 2. Binance (backup #1)\n * 3. CoinGecko (backup #2)\n * 4. Kraken (backup #3)\n * \n * @example\n * ```typescript\n * const { solPrice, source } = await getSolPrice();\n * console.log(`SOL is $${solPrice} (from ${source})`);\n * ```\n */\nexport async function getSolPrice(): Promise<PriceData> {\n const cacheTTL = config.cacheTTL ?? 60000;\n const timeout = config.timeout ?? 5000;\n\n // Return cached price if valid\n if (cachedPrice && Date.now() - cachedPrice.fetchedAt.getTime() < cacheTTL) {\n return cachedPrice;\n }\n\n // Try custom provider first if configured\n if (config.customProvider) {\n try {\n const price = await config.customProvider();\n if (price > 0) {\n cachedPrice = {\n solPrice: price,\n fetchedAt: new Date(),\n source: 'custom',\n };\n return cachedPrice;\n }\n } catch {\n // Fall through to built-in providers\n }\n }\n\n // Try providers in rotation, starting after the last successful one\n for (let i = 0; i < PROVIDERS.length; i++) {\n const idx = (lastProviderIndex + 1 + i) % PROVIDERS.length;\n const provider = PROVIDERS[idx];\n\n try {\n const price = await fetchFromProvider(provider, timeout);\n lastProviderIndex = idx;\n\n cachedPrice = {\n solPrice: price,\n fetchedAt: new Date(),\n source: provider.name,\n };\n return cachedPrice;\n } catch {\n // Try next provider\n continue;\n }\n }\n\n // All providers failed, use stale cache if available\n if (cachedPrice) {\n // Mark as stale but still usable\n return {\n ...cachedPrice,\n source: `${cachedPrice.source} (stale)`,\n };\n }\n\n // SECURITY: Never use hardcoded fallback - throw error instead\n throw new Error(\n 'Failed to fetch SOL price from all providers. ' +\n 'Configure a custom provider or ensure network connectivity.'\n );\n}\n\n/**\n * Convert lamports to USD\n * \n * @example\n * ```typescript\n * const usd = await lamportsToUsd(10_000_000n); // 0.01 SOL\n * console.log(`$${usd.toFixed(2)}`);\n * ```\n */\nexport async function lamportsToUsd(lamports: bigint): Promise<number> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000;\n return sol * solPrice;\n}\n\n/**\n * Convert USD to lamports\n * \n * @example\n * ```typescript\n * const lamports = await usdToLamports(1.50); // $1.50\n * console.log(`${lamports} lamports`);\n * ```\n */\nexport async function usdToLamports(usd: number): Promise<bigint> {\n const { solPrice } = await getSolPrice();\n const sol = usd / solPrice;\n return BigInt(Math.floor(sol * 1_000_000_000));\n}\n\n/**\n * Format a price for display with both SOL and USD\n * \n * @example\n * ```typescript\n * const display = await formatPriceDisplay(10_000_000n);\n * // Returns: \"0.0100 SOL (~$1.50)\"\n * ```\n */\nexport async function formatPriceDisplay(lamports: bigint): Promise<string> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`;\n}\n\n/**\n * Synchronous price formatting (requires pre-fetched price)\n */\nexport function formatPriceSync(lamports: bigint, solPrice: number): {\n sol: number;\n usd: number;\n formatted: string;\n} {\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return {\n sol,\n usd,\n formatted: `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`,\n };\n}\n\n/**\n * Clear the price cache (for testing or manual refresh)\n */\nexport function clearPriceCache(): void {\n cachedPrice = null;\n lastProviderIndex = -1;\n}\n\n/**\n * Get list of available built-in providers\n */\nexport function getProviders(): { name: string; url: string }[] {\n return PROVIDERS.map(p => ({ name: p.name, url: p.url }));\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/pricing/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// Price Conversion Helpers\n// Multi-provider SOL price fetching with fallback rotation\n\n/**\n * Price data from API\n */\nexport interface PriceData {\n /** SOL price in USD */\n solPrice: number;\n /** Timestamp of price fetch */\n fetchedAt: Date;\n /** Source of price data */\n source: string;\n}\n\n/**\n * Custom price provider function type\n */\nexport type CustomPriceProvider = () => Promise<number>;\n\n/**\n * Price provider configuration\n */\nexport interface PriceConfig {\n /** Custom price provider (if set, skips built-in providers) */\n customProvider?: CustomPriceProvider;\n /** Cache TTL in milliseconds (default: 60000) */\n cacheTTL?: number;\n /** Request timeout in milliseconds (default: 5000) */\n timeout?: number;\n}\n\n// Cached price data\nlet cachedPrice: PriceData | null = null;\nlet config: PriceConfig = {};\nlet lastProviderIndex = -1;\n\n/**\n * Configure price fetching\n * \n * @example\n * ```typescript\n * // Use custom API\n * configurePricing({\n * customProvider: async () => {\n * const res = await fetch('https://my-api.com/sol-price');\n * return (await res.json()).price;\n * },\n * });\n * \n * // Or just adjust cache TTL\n * configurePricing({ cacheTTL: 30000 }); // 30 seconds\n * ```\n */\nexport function configurePricing(newConfig: PriceConfig): void {\n config = { ...config, ...newConfig };\n cachedPrice = null; // Clear cache on config change\n}\n\n/**\n * Built-in price providers with reliability rotation\n */\nconst PROVIDERS = [\n {\n name: 'coincap',\n url: 'https://api.coincap.io/v2/assets/solana',\n parse: (data: { data?: { priceUsd?: string } }) => parseFloat(data.data?.priceUsd || '0'),\n },\n {\n name: 'binance',\n url: 'https://api.binance.com/api/v3/ticker/price?symbol=SOLUSDT',\n parse: (data: { price?: string }) => parseFloat(data.price || '0'),\n },\n {\n name: 'coingecko',\n url: 'https://api.coingecko.com/api/v3/simple/price?ids=solana&vs_currencies=usd',\n parse: (data: { solana?: { usd?: number } }) => data.solana?.usd || 0,\n },\n {\n name: 'kraken',\n url: 'https://api.kraken.com/0/public/Ticker?pair=SOLUSD',\n parse: (data: { result?: { SOLUSD?: { c?: string[] } } }) =>\n parseFloat(data.result?.SOLUSD?.c?.[0] || '0'),\n },\n];\n\n/**\n * Fetch price from a single provider\n */\nasync function fetchFromProvider(\n provider: typeof PROVIDERS[0],\n timeout: number\n): Promise<number> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(provider.url, {\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const data = await response.json() as Record<string, unknown>;\n const price = provider.parse(data as Parameters<typeof provider.parse>[0]);\n\n if (!price || price <= 0) {\n throw new Error('Invalid price');\n }\n\n return price;\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\n/**\n * Get SOL price with multi-provider fallback\n * \n * Provider rotation order:\n * 1. CoinCap (primary)\n * 2. Binance (backup #1)\n * 3. CoinGecko (backup #2)\n * 4. Kraken (backup #3)\n * \n * @example\n * ```typescript\n * const { solPrice, source } = await getSolPrice();\n * console.log(`SOL is $${solPrice} (from ${source})`);\n * ```\n */\nexport async function getSolPrice(): Promise<PriceData> {\n const cacheTTL = config.cacheTTL ?? 60000;\n const timeout = config.timeout ?? 5000;\n\n // Return cached price if valid\n if (cachedPrice && Date.now() - cachedPrice.fetchedAt.getTime() < cacheTTL) {\n return cachedPrice;\n }\n\n // Try custom provider first if configured\n if (config.customProvider) {\n try {\n const price = await config.customProvider();\n if (price > 0) {\n cachedPrice = {\n solPrice: price,\n fetchedAt: new Date(),\n source: 'custom',\n };\n return cachedPrice;\n }\n } catch {\n // Fall through to built-in providers\n }\n }\n\n // Try providers in rotation, starting after the last successful one\n for (let i = 0; i < PROVIDERS.length; i++) {\n const idx = (lastProviderIndex + 1 + i) % PROVIDERS.length;\n const provider = PROVIDERS[idx];\n\n try {\n const price = await fetchFromProvider(provider, timeout);\n lastProviderIndex = idx;\n\n cachedPrice = {\n solPrice: price,\n fetchedAt: new Date(),\n source: provider.name,\n };\n return cachedPrice;\n } catch {\n // Try next provider\n continue;\n }\n }\n\n // All providers failed, use stale cache if available\n if (cachedPrice) {\n // Mark as stale but still usable\n return {\n ...cachedPrice,\n source: `${cachedPrice.source} (stale)`,\n };\n }\n\n // SECURITY: Never use hardcoded fallback - throw error instead\n throw new Error(\n 'Failed to fetch SOL price from all providers. ' +\n 'Configure a custom provider or ensure network connectivity.'\n );\n}\n\n/**\n * Convert lamports to USD\n * \n * @example\n * ```typescript\n * const usd = await lamportsToUsd(10_000_000n); // 0.01 SOL\n * console.log(`$${usd.toFixed(2)}`);\n * ```\n */\nexport async function lamportsToUsd(lamports: bigint): Promise<number> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000;\n return sol * solPrice;\n}\n\n/**\n * Convert USD to lamports\n * \n * @example\n * ```typescript\n * const lamports = await usdToLamports(1.50); // $1.50\n * console.log(`${lamports} lamports`);\n * ```\n */\nexport async function usdToLamports(usd: number): Promise<bigint> {\n const { solPrice } = await getSolPrice();\n const sol = usd / solPrice;\n return BigInt(Math.floor(sol * 1_000_000_000));\n}\n\n/**\n * Format a price for display with both SOL and USD\n * \n * @example\n * ```typescript\n * const display = await formatPriceDisplay(10_000_000n);\n * // Returns: \"0.0100 SOL (~$1.50)\"\n * ```\n */\nexport async function formatPriceDisplay(lamports: bigint): Promise<string> {\n const { solPrice } = await getSolPrice();\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`;\n}\n\n/**\n * Synchronous price formatting (requires pre-fetched price)\n */\nexport function formatPriceSync(lamports: bigint, solPrice: number): {\n sol: number;\n usd: number;\n formatted: string;\n} {\n const sol = Number(lamports) / 1_000_000_000;\n const usd = sol * solPrice;\n\n return {\n sol,\n usd,\n formatted: `${sol.toFixed(4)} SOL (~$${usd.toFixed(2)})`,\n };\n}\n\n/**\n * Clear the price cache (for testing or manual refresh)\n */\nexport function clearPriceCache(): void {\n cachedPrice = null;\n lastProviderIndex = -1;\n}\n\n/**\n * Get list of available built-in providers\n */\nexport function getProviders(): { name: string; url: string }[] {\n return PROVIDERS.map(p => ({ name: p.name, url: p.url }));\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/session/core.ts"],"names":["uuidv4","SignJWT","jwtVerify"],"mappings":"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","file":"index.cjs","sourcesContent":["// Session management with JWT (framework-agnostic core)\n// SECURITY: Uses jose library with HS256, constant-time validation, input sanitization\nimport { SignJWT, jwtVerify } from 'jose';\nimport { v4 as uuidv4 } from 'uuid';\nimport type { SessionData, SessionConfig, SessionValidation, SessionJWTPayload } from './types';\n\n// Maximum articles per session to prevent unbounded growth\nconst MAX_ARTICLES_PER_SESSION = 100;\n\n// Minimum secret length for security\nconst MIN_SECRET_LENGTH = 32;\n\n/**\n * Get the secret key for JWT signing\n * SECURITY: Enforces minimum secret length\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 (base58, 32-44 chars)\n * SECURITY: Prevents injection via wallet address field\n */\nfunction validateWalletAddress(address: string): boolean {\n if (!address || typeof address !== 'string') return false;\n // Solana addresses are base58, typically 32-44 characters\n const base58Regex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n return base58Regex.test(address);\n}\n\n/**\n * Validate article ID format\n * SECURITY: Prevents injection via articleId field\n */\nfunction validateArticleId(articleId: string): boolean {\n if (!articleId || typeof articleId !== 'string') return false;\n // Allow alphanumeric, hyphens, underscores, max 128 chars\n if (articleId.length > 128) return false;\n const safeIdRegex = /^[a-zA-Z0-9_-]+$/;\n return safeIdRegex.test(articleId);\n}\n\n/**\n * Create a new session after successful payment\n * SECURITY: Validates inputs, enforces limits\n */\nexport async function createSession(\n walletAddress: string,\n articleId: string,\n config: SessionConfig,\n siteWide: boolean = false\n): Promise<{ token: string; session: SessionData }> {\n // Input validation\n if (!validateWalletAddress(walletAddress)) {\n throw new Error('Invalid wallet address format');\n }\n if (!validateArticleId(articleId)) {\n throw new Error('Invalid article ID format');\n }\n if (!config.durationHours || config.durationHours <= 0 || config.durationHours > 720) {\n throw new Error('Session duration must be between 1 and 720 hours');\n }\n\n const sessionId = uuidv4();\n const now = Math.floor(Date.now() / 1000);\n const expiresAt = now + (config.durationHours * 3600);\n\n const session: SessionData = {\n id: sessionId,\n walletAddress,\n unlockedArticles: [articleId],\n siteWideUnlock: Boolean(siteWide),\n createdAt: now,\n expiresAt,\n };\n\n const payload: SessionJWTPayload = {\n sub: walletAddress,\n sid: sessionId,\n articles: session.unlockedArticles,\n siteWide: session.siteWideUnlock,\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/**\n * Validate an existing session token\n * SECURITY: jose library handles timing-safe comparison internally\n */\nexport async function validateSession(\n token: string,\n secret: string\n): Promise<SessionValidation> {\n // Input validation\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 sessionPayload = payload as unknown as SessionJWTPayload;\n\n // Validate required fields exist\n if (!sessionPayload.sub || !sessionPayload.sid || !sessionPayload.exp) {\n return { valid: false, reason: 'Malformed session payload' };\n }\n\n // Check expiration (jose already checks, but double-check)\n const now = Math.floor(Date.now() / 1000);\n if (sessionPayload.exp < now) {\n return { valid: false, reason: 'Session expired' };\n }\n\n // Validate wallet address format from token\n if (!validateWalletAddress(sessionPayload.sub)) {\n return { valid: false, reason: 'Invalid session data' };\n }\n\n const session: SessionData = {\n id: sessionPayload.sid,\n walletAddress: sessionPayload.sub,\n unlockedArticles: Array.isArray(sessionPayload.articles) ? sessionPayload.articles : [],\n siteWideUnlock: Boolean(sessionPayload.siteWide),\n createdAt: sessionPayload.iat ?? 0,\n expiresAt: sessionPayload.exp,\n };\n\n return { valid: true, session };\n } catch (error) {\n // SECURITY: Don't expose internal error details\n return { valid: false, reason: 'Invalid session' };\n }\n}\n\n/**\n * Add an article to an existing session\n * SECURITY: Enforces article limit to prevent token bloat\n */\nexport async function addArticleToSession(\n token: string,\n articleId: string,\n secret: string\n): Promise<{ token: string; session: SessionData } | null> {\n // Validate article ID\n if (!validateArticleId(articleId)) {\n return null;\n }\n\n const validation = await validateSession(token, secret);\n if (!validation.valid || !validation.session) {\n return null;\n }\n\n const session = validation.session;\n\n // Already unlocked\n if (session.unlockedArticles.includes(articleId)) {\n return { token, session };\n }\n\n // SECURITY: Enforce maximum articles per session\n if (session.unlockedArticles.length >= MAX_ARTICLES_PER_SESSION) {\n return null;\n }\n\n const updatedArticles = [...session.unlockedArticles, articleId];\n\n const payload: SessionJWTPayload = {\n sub: session.walletAddress,\n sid: session.id,\n articles: updatedArticles,\n siteWide: session.siteWideUnlock,\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 token: newToken,\n session: { ...session, unlockedArticles: updatedArticles },\n };\n}\n\n/**\n * Check if an article is unlocked for a session\n */\nexport async function isArticleUnlocked(\n token: string,\n articleId: string,\n secret: string\n): Promise<boolean> {\n if (!validateArticleId(articleId)) {\n return false;\n }\n\n const validation = await validateSession(token, secret);\n if (!validation.valid || !validation.session) {\n return false;\n }\n\n if (validation.session.siteWideUnlock) {\n return true;\n }\n\n return validation.session.unlockedArticles.includes(articleId);\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/session/core.ts"],"names":["uuidv4"],"mappings":"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","file":"index.js","sourcesContent":["// Session management with JWT (framework-agnostic core)\n// SECURITY: Uses jose library with HS256, constant-time validation, input sanitization\nimport { SignJWT, jwtVerify } from 'jose';\nimport { v4 as uuidv4 } from 'uuid';\nimport type { SessionData, SessionConfig, SessionValidation, SessionJWTPayload } from './types';\n\n// Maximum articles per session to prevent unbounded growth\nconst MAX_ARTICLES_PER_SESSION = 100;\n\n// Minimum secret length for security\nconst MIN_SECRET_LENGTH = 32;\n\n/**\n * Get the secret key for JWT signing\n * SECURITY: Enforces minimum secret length\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 (base58, 32-44 chars)\n * SECURITY: Prevents injection via wallet address field\n */\nfunction validateWalletAddress(address: string): boolean {\n if (!address || typeof address !== 'string') return false;\n // Solana addresses are base58, typically 32-44 characters\n const base58Regex = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n return base58Regex.test(address);\n}\n\n/**\n * Validate article ID format\n * SECURITY: Prevents injection via articleId field\n */\nfunction validateArticleId(articleId: string): boolean {\n if (!articleId || typeof articleId !== 'string') return false;\n // Allow alphanumeric, hyphens, underscores, max 128 chars\n if (articleId.length > 128) return false;\n const safeIdRegex = /^[a-zA-Z0-9_-]+$/;\n return safeIdRegex.test(articleId);\n}\n\n/**\n * Create a new session after successful payment\n * SECURITY: Validates inputs, enforces limits\n */\nexport async function createSession(\n walletAddress: string,\n articleId: string,\n config: SessionConfig,\n siteWide: boolean = false\n): Promise<{ token: string; session: SessionData }> {\n // Input validation\n if (!validateWalletAddress(walletAddress)) {\n throw new Error('Invalid wallet address format');\n }\n if (!validateArticleId(articleId)) {\n throw new Error('Invalid article ID format');\n }\n if (!config.durationHours || config.durationHours <= 0 || config.durationHours > 720) {\n throw new Error('Session duration must be between 1 and 720 hours');\n }\n\n const sessionId = uuidv4();\n const now = Math.floor(Date.now() / 1000);\n const expiresAt = now + (config.durationHours * 3600);\n\n const session: SessionData = {\n id: sessionId,\n walletAddress,\n unlockedArticles: [articleId],\n siteWideUnlock: Boolean(siteWide),\n createdAt: now,\n expiresAt,\n };\n\n const payload: SessionJWTPayload = {\n sub: walletAddress,\n sid: sessionId,\n articles: session.unlockedArticles,\n siteWide: session.siteWideUnlock,\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/**\n * Validate an existing session token\n * SECURITY: jose library handles timing-safe comparison internally\n */\nexport async function validateSession(\n token: string,\n secret: string\n): Promise<SessionValidation> {\n // Input validation\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 sessionPayload = payload as unknown as SessionJWTPayload;\n\n // Validate required fields exist\n if (!sessionPayload.sub || !sessionPayload.sid || !sessionPayload.exp) {\n return { valid: false, reason: 'Malformed session payload' };\n }\n\n // Check expiration (jose already checks, but double-check)\n const now = Math.floor(Date.now() / 1000);\n if (sessionPayload.exp < now) {\n return { valid: false, reason: 'Session expired' };\n }\n\n // Validate wallet address format from token\n if (!validateWalletAddress(sessionPayload.sub)) {\n return { valid: false, reason: 'Invalid session data' };\n }\n\n const session: SessionData = {\n id: sessionPayload.sid,\n walletAddress: sessionPayload.sub,\n unlockedArticles: Array.isArray(sessionPayload.articles) ? sessionPayload.articles : [],\n siteWideUnlock: Boolean(sessionPayload.siteWide),\n createdAt: sessionPayload.iat ?? 0,\n expiresAt: sessionPayload.exp,\n };\n\n return { valid: true, session };\n } catch (error) {\n // SECURITY: Don't expose internal error details\n return { valid: false, reason: 'Invalid session' };\n }\n}\n\n/**\n * Add an article to an existing session\n * SECURITY: Enforces article limit to prevent token bloat\n */\nexport async function addArticleToSession(\n token: string,\n articleId: string,\n secret: string\n): Promise<{ token: string; session: SessionData } | null> {\n // Validate article ID\n if (!validateArticleId(articleId)) {\n return null;\n }\n\n const validation = await validateSession(token, secret);\n if (!validation.valid || !validation.session) {\n return null;\n }\n\n const session = validation.session;\n\n // Already unlocked\n if (session.unlockedArticles.includes(articleId)) {\n return { token, session };\n }\n\n // SECURITY: Enforce maximum articles per session\n if (session.unlockedArticles.length >= MAX_ARTICLES_PER_SESSION) {\n return null;\n }\n\n const updatedArticles = [...session.unlockedArticles, articleId];\n\n const payload: SessionJWTPayload = {\n sub: session.walletAddress,\n sid: session.id,\n articles: updatedArticles,\n siteWide: session.siteWideUnlock,\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 token: newToken,\n session: { ...session, unlockedArticles: updatedArticles },\n };\n}\n\n/**\n * Check if an article is unlocked for a session\n */\nexport async function isArticleUnlocked(\n token: string,\n articleId: string,\n secret: string\n): Promise<boolean> {\n if (!validateArticleId(articleId)) {\n return false;\n }\n\n const validation = await validateSession(token, secret);\n if (!validation.valid || !validation.session) {\n return false;\n }\n\n if (validation.session.siteWideUnlock) {\n return true;\n }\n\n return validation.session.unlockedArticles.includes(articleId);\n}\n"]}
|