@alleyboss/micropay-solana-x402-paywall 3.3.11 → 3.3.13

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/README.md CHANGED
@@ -22,6 +22,7 @@ npm install @alleyboss/micropay-solana-x402-paywall @x402/core @x402/svm @solana
22
22
  |---------|-------------|--------|
23
23
  | 💰 **SOL & USDC** | Native SOL and SPL tokens (USDC, USDT) | ✅ Verified by `@x402/svm` |
24
24
  | 🔐 **x402 Protocol** | Full HTTP 402 compliance | ✅ Powered by `@x402/core` |
25
+ | 🌐 **PayAI Format** | Multi-chain payment format support | ✅ Built-in |
25
26
  | 🔑 **JWT Sessions** | "Pay once, unlock for 24h" logic | ✅ Built-in (Hybrid Support) |
26
27
  | 🛡️ **Replay Protection** | Prevent double-spend / replay attacks | ✅ Managed by x402 Facilitator |
27
28
  | 🔌 **Express Integration** | Middleware for Express/Node.js | ✅ Built-in |
@@ -133,6 +134,61 @@ const withMicropay = createX402Middleware({
133
134
  | **Setup** | Zero-config | Requires RPC URL |
134
135
  | **Best For** | Quick startups, MVPs | Production, High-Volume, Agents |
135
136
 
137
+ ## 🌐 PayAI Format Support (New in v3.3.13)
138
+
139
+ Native support for the **PayAI payment format** - a universal payment protocol that works across Solana, Ethereum, Base, and other chains.
140
+
141
+ ```typescript
142
+ // PayAI format is automatically detected and processed
143
+ const payaiPayload = {
144
+ scheme: 'exact-svm',
145
+ networkId: 'solana-devnet',
146
+ authorization: {
147
+ signatures: ['5j8...']
148
+ }
149
+ };
150
+
151
+ const response = await fetch('/api/premium', {
152
+ headers: {
153
+ 'Authorization': `x402 ${btoa(JSON.stringify(payaiPayload))}`
154
+ }
155
+ });
156
+ ```
157
+
158
+ **Features:**
159
+ - ✅ Automatic format detection and transformation
160
+ - ✅ Multi-chain ready (Solana, Ethereum, Base)
161
+ - ✅ Full TypeScript support
162
+ - ✅ Backward compatible with x402 format
163
+
164
+ **Learn more:** [PayAI Integration Guide](https://github.com/AlleyBo55/micropay-solana-x402-paywall/blob/main/docs/PAYAI_INTEGRATION.md)
165
+
166
+ ## 🌐 Public Facilitator Mode (New in v3.3.12)
167
+
168
+ Use a public facilitator service like [x402.org](https://x402.org) or [PayAI Network](https://facilitator.payai.network) without running your own RPC node:
169
+
170
+ ```typescript
171
+ import { RemoteSvmFacilitator } from '@alleyboss/micropay-solana-x402-paywall';
172
+
173
+ // Use a public facilitator for verification
174
+ const facilitator = new RemoteSvmFacilitator('https://x402.org/facilitator');
175
+
176
+ // Or in middleware config
177
+ const withMicropay = createX402Middleware({
178
+ walletAddress: 'YOUR_WALLET',
179
+ network: 'mainnet-beta',
180
+ facilitatorUrl: 'https://facilitator.payai.network'
181
+ // No rpcUrl = uses remote facilitator
182
+ });
183
+ ```
184
+
185
+ ### 🆚 Verification Modes Comparison
186
+
187
+ | Mode | Class | Best For |
188
+ |------|-------|----------|
189
+ | **Self-Sovereign** | `LocalSvmFacilitator` | Full control, privacy, production |
190
+ | **Public Facilitator** | `RemoteSvmFacilitator` | Quick setup, no RPC management |
191
+
136
192
  ## 🤖 AI Agent Payments
137
193
 
138
194
  Enable autonomous AI agents to pay for premium API access.
@@ -1,5 +1,5 @@
1
1
  import { Connection, Keypair } from '@solana/web3.js';
2
- import { S as SessionConfig, a as SessionData } from '../types-BWYQMw03.cjs';
2
+ import { S as SessionConfig, a as SessionData } from '../types-BfKfgout.cjs';
3
3
 
4
4
  /** Configuration for priority fees */
5
5
  interface PriorityFeeConfig {
@@ -1,5 +1,5 @@
1
1
  import { Connection, Keypair } from '@solana/web3.js';
2
- import { S as SessionConfig, a as SessionData } from '../types-BWYQMw03.js';
2
+ import { S as SessionConfig, a as SessionData } from '../types-BfKfgout.js';
3
3
 
4
4
  /** Configuration for priority fees */
5
5
  interface PriorityFeeConfig {
@@ -100,13 +100,9 @@ function createX402AuthorizationHeader(signature, paymentRequiredHeader) {
100
100
  const required = http.decodePaymentRequiredHeader(cleanHeader);
101
101
  const accepts = Array.isArray(required.accepts) ? required.accepts[0] : required.accepts;
102
102
  const payload = {
103
- accepted: accepts,
104
- client: {
105
- scheme: accepts.scheme,
106
- // TypeScript knows this exists on PaymentRequirements
107
- network: accepts.network
108
- },
109
- payment: {
103
+ scheme: accepts.scheme,
104
+ network: accepts.network,
105
+ payload: {
110
106
  signature
111
107
  }
112
108
  };
@@ -233,20 +229,28 @@ function usePaywallResource({
233
229
  const unlock = react.useCallback(async () => {
234
230
  if (!paymentHeader || !price || !recipient) {
235
231
  setError("Missing payment requirements");
232
+ console.error("[usePaywallResource] Missing requirements:", { paymentHeader: !!paymentHeader, price, recipient });
236
233
  return;
237
234
  }
238
235
  setIsLoading(true);
236
+ console.log("[usePaywallResource] Starting unlock. Price:", price.toString(), "Recipient:", recipient);
239
237
  try {
238
+ console.log("[usePaywallResource] Step 1: Sending payment...");
240
239
  const { signature } = await sendSolanaPayment({
241
240
  connection,
242
241
  wallet,
243
242
  recipientAddress: recipient,
244
243
  amount: price
245
244
  });
245
+ console.log("[usePaywallResource] Step 1 Complete: Payment signature:", signature);
246
+ console.log("[usePaywallResource] Step 2: Creating auth header...");
246
247
  const authHeader = createX402AuthorizationHeader(signature, paymentHeader);
248
+ console.log("[usePaywallResource] Step 2 Complete: Auth header created (length:", authHeader.length, ")");
249
+ console.log("[usePaywallResource] Step 3: Retrying fetch with auth header...");
247
250
  await fetchData(authHeader);
251
+ console.log("[usePaywallResource] Step 3 Complete: Fetch completed");
248
252
  } catch (err) {
249
- console.error("Unlock failed", err);
253
+ console.error("[usePaywallResource] Unlock failed at step:", err);
250
254
  setError(err.message || "Payment/Unlock failed");
251
255
  setIsLoading(false);
252
256
  }
@@ -98,13 +98,9 @@ function createX402AuthorizationHeader(signature, paymentRequiredHeader) {
98
98
  const required = decodePaymentRequiredHeader(cleanHeader);
99
99
  const accepts = Array.isArray(required.accepts) ? required.accepts[0] : required.accepts;
100
100
  const payload = {
101
- accepted: accepts,
102
- client: {
103
- scheme: accepts.scheme,
104
- // TypeScript knows this exists on PaymentRequirements
105
- network: accepts.network
106
- },
107
- payment: {
101
+ scheme: accepts.scheme,
102
+ network: accepts.network,
103
+ payload: {
108
104
  signature
109
105
  }
110
106
  };
@@ -231,20 +227,28 @@ function usePaywallResource({
231
227
  const unlock = useCallback(async () => {
232
228
  if (!paymentHeader || !price || !recipient) {
233
229
  setError("Missing payment requirements");
230
+ console.error("[usePaywallResource] Missing requirements:", { paymentHeader: !!paymentHeader, price, recipient });
234
231
  return;
235
232
  }
236
233
  setIsLoading(true);
234
+ console.log("[usePaywallResource] Starting unlock. Price:", price.toString(), "Recipient:", recipient);
237
235
  try {
236
+ console.log("[usePaywallResource] Step 1: Sending payment...");
238
237
  const { signature } = await sendSolanaPayment({
239
238
  connection,
240
239
  wallet,
241
240
  recipientAddress: recipient,
242
241
  amount: price
243
242
  });
243
+ console.log("[usePaywallResource] Step 1 Complete: Payment signature:", signature);
244
+ console.log("[usePaywallResource] Step 2: Creating auth header...");
244
245
  const authHeader = createX402AuthorizationHeader(signature, paymentHeader);
246
+ console.log("[usePaywallResource] Step 2 Complete: Auth header created (length:", authHeader.length, ")");
247
+ console.log("[usePaywallResource] Step 3: Retrying fetch with auth header...");
245
248
  await fetchData(authHeader);
249
+ console.log("[usePaywallResource] Step 3 Complete: Fetch completed");
246
250
  } catch (err) {
247
- console.error("Unlock failed", err);
251
+ console.error("[usePaywallResource] Unlock failed at step:", err);
248
252
  setError(err.message || "Payment/Unlock failed");
249
253
  setIsLoading(false);
250
254
  }
package/dist/index.cjs CHANGED
@@ -18,7 +18,6 @@ var LocalSvmFacilitator = class {
18
18
  caipFamily = "solana:*";
19
19
  connection;
20
20
  constructor(rpcUrl) {
21
- console.log("[LocalSvmFacilitator] Initialized with RPC:", rpcUrl);
22
21
  this.connection = new web3_js.Connection(rpcUrl, "confirmed");
23
22
  }
24
23
  /**
@@ -102,25 +101,18 @@ var LocalSvmFacilitator = class {
102
101
  getSigners(_network) {
103
102
  return [];
104
103
  }
105
- /**
106
- * Enable debug logging (disable in production)
107
- */
108
- debug = process.env.NODE_ENV === "development";
109
104
  /**
110
105
  * Verify a payment on-chain
111
106
  */
112
107
  async verify(payload, requirements) {
113
108
  try {
114
- const signature = payload.payload.signature;
109
+ const signature = payload.payload?.signature;
115
110
  if (!signature) {
116
111
  return { isValid: false, invalidReason: "Missing signature in payment payload" };
117
112
  }
118
113
  const payTo = requirements.payTo;
119
114
  const amountVal = requirements.amount || requirements.maxAmountRequired || "0";
120
115
  const requiredAmount = BigInt(amountVal);
121
- if (this.debug) {
122
- console.log(`[LocalSvmFacilitator] Verifying tx: ${signature.slice(0, 8)}...`);
123
- }
124
116
  const tx = await this.fetchTransactionWithRetry(signature, 3);
125
117
  if (!tx) {
126
118
  return { isValid: false, invalidReason: "Transaction not found or not confirmed" };
@@ -136,19 +128,8 @@ var LocalSvmFacilitator = class {
136
128
  if (!payer) payer = parsed.info.source;
137
129
  }
138
130
  }
139
- if ("program" in ix && (ix.program === "spl-token" || ix.program === "spl-token-2022")) {
140
- const parsed = ix.parsed;
141
- if (parsed?.type === "transferChecked" || parsed?.type === "transfer") {
142
- if (this.debug) {
143
- console.log(`[LocalSvmFacilitator] Found SPL transfer`);
144
- }
145
- }
146
- }
147
131
  }
148
132
  if (paidAmount >= requiredAmount) {
149
- if (this.debug) {
150
- console.log(`[LocalSvmFacilitator] Verification SUCCESS for tx: ${signature.slice(0, 8)}...`);
151
- }
152
133
  return {
153
134
  isValid: true,
154
135
  payer: payer || tx.transaction.message.accountKeys[0].pubkey.toBase58()
@@ -161,9 +142,6 @@ var LocalSvmFacilitator = class {
161
142
  };
162
143
  } catch (error) {
163
144
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
164
- if (this.debug) {
165
- console.error("[LocalSvmFacilitator] Verify error:", errorMessage);
166
- }
167
145
  throw new types.VerifyError(500, {
168
146
  isValid: false,
169
147
  invalidReason: errorMessage
package/dist/index.d.cts CHANGED
@@ -6,7 +6,7 @@ export * from '@x402/svm';
6
6
  export { AgentPaymentResult, CreditSessionClaims, CreditSessionConfig, CreditSessionData, CreditValidation, ExecuteAgentPaymentParams, UseCreditResult, addCredits, createCreditSession, executeAgentPayment, generateAgentKeypair, getAgentBalance, getRemainingCredits, hasAgentSufficientBalance, keypairFromBase58, useCredit, validateCreditSession } from './agent/index.cjs';
7
7
  export { CustomPriceProvider, PriceConfig, PriceData, clearPriceCache, configurePricing, formatPriceDisplay, formatPriceSync, getProviders, getSolPrice, lamportsToSol, lamportsToUsd, usdToLamports } from './pricing/index.cjs';
8
8
  import '@solana/web3.js';
9
- import './types-BWYQMw03.cjs';
9
+ import './types-BfKfgout.cjs';
10
10
 
11
11
  interface FacilitatorClient$1 {
12
12
  verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<VerifyResponse>;
@@ -75,10 +75,6 @@ declare class LocalSvmFacilitator implements FacilitatorClient$1 {
75
75
  * Get default signers (not used for local verification usually, but required by interface)
76
76
  */
77
77
  getSigners(_network: string): string[];
78
- /**
79
- * Enable debug logging (disable in production)
80
- */
81
- private debug;
82
78
  /**
83
79
  * Verify a payment on-chain
84
80
  */
@@ -127,4 +123,32 @@ declare class RemoteSvmFacilitator implements FacilitatorClient {
127
123
  settle(payload: PaymentPayload, requirements: PaymentRequirements): Promise<SettleResponse>;
128
124
  }
129
125
 
130
- export { LocalSvmFacilitator, RemoteSvmFacilitator };
126
+ /**
127
+ * PayAI Payment Format Types
128
+ */
129
+ type PayAIScheme = 'exact-evm' | 'exact-svm' | string;
130
+ type PayAINetworkId = 'base' | 'solana' | 'solana-devnet' | 'polygon-amoy' | string;
131
+ interface PayAISvmAuthorization {
132
+ message?: string;
133
+ signatures?: string[];
134
+ }
135
+ interface PayAIEvmAuthorization {
136
+ from: string;
137
+ to: string;
138
+ value: string;
139
+ data: string;
140
+ validAfter: number;
141
+ validBefore: number;
142
+ nonce: string;
143
+ v: number;
144
+ r: string;
145
+ s: string;
146
+ }
147
+ interface PayAIPayload {
148
+ scheme: PayAIScheme;
149
+ networkId: PayAINetworkId;
150
+ paymentDetails?: Record<string, any>;
151
+ authorization: PayAISvmAuthorization | PayAIEvmAuthorization | Record<string, any>;
152
+ }
153
+
154
+ export { LocalSvmFacilitator, type PayAIEvmAuthorization, type PayAINetworkId, type PayAIPayload, type PayAIScheme, type PayAISvmAuthorization, RemoteSvmFacilitator };
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export * from '@x402/svm';
6
6
  export { AgentPaymentResult, CreditSessionClaims, CreditSessionConfig, CreditSessionData, CreditValidation, ExecuteAgentPaymentParams, UseCreditResult, addCredits, createCreditSession, executeAgentPayment, generateAgentKeypair, getAgentBalance, getRemainingCredits, hasAgentSufficientBalance, keypairFromBase58, useCredit, validateCreditSession } from './agent/index.js';
7
7
  export { CustomPriceProvider, PriceConfig, PriceData, clearPriceCache, configurePricing, formatPriceDisplay, formatPriceSync, getProviders, getSolPrice, lamportsToSol, lamportsToUsd, usdToLamports } from './pricing/index.js';
8
8
  import '@solana/web3.js';
9
- import './types-BWYQMw03.js';
9
+ import './types-BfKfgout.js';
10
10
 
11
11
  interface FacilitatorClient$1 {
12
12
  verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<VerifyResponse>;
@@ -75,10 +75,6 @@ declare class LocalSvmFacilitator implements FacilitatorClient$1 {
75
75
  * Get default signers (not used for local verification usually, but required by interface)
76
76
  */
77
77
  getSigners(_network: string): string[];
78
- /**
79
- * Enable debug logging (disable in production)
80
- */
81
- private debug;
82
78
  /**
83
79
  * Verify a payment on-chain
84
80
  */
@@ -127,4 +123,32 @@ declare class RemoteSvmFacilitator implements FacilitatorClient {
127
123
  settle(payload: PaymentPayload, requirements: PaymentRequirements): Promise<SettleResponse>;
128
124
  }
129
125
 
130
- export { LocalSvmFacilitator, RemoteSvmFacilitator };
126
+ /**
127
+ * PayAI Payment Format Types
128
+ */
129
+ type PayAIScheme = 'exact-evm' | 'exact-svm' | string;
130
+ type PayAINetworkId = 'base' | 'solana' | 'solana-devnet' | 'polygon-amoy' | string;
131
+ interface PayAISvmAuthorization {
132
+ message?: string;
133
+ signatures?: string[];
134
+ }
135
+ interface PayAIEvmAuthorization {
136
+ from: string;
137
+ to: string;
138
+ value: string;
139
+ data: string;
140
+ validAfter: number;
141
+ validBefore: number;
142
+ nonce: string;
143
+ v: number;
144
+ r: string;
145
+ s: string;
146
+ }
147
+ interface PayAIPayload {
148
+ scheme: PayAIScheme;
149
+ networkId: PayAINetworkId;
150
+ paymentDetails?: Record<string, any>;
151
+ authorization: PayAISvmAuthorization | PayAIEvmAuthorization | Record<string, any>;
152
+ }
153
+
154
+ export { LocalSvmFacilitator, type PayAIEvmAuthorization, type PayAINetworkId, type PayAIPayload, type PayAIScheme, type PayAISvmAuthorization, RemoteSvmFacilitator };
package/dist/index.js CHANGED
@@ -13,7 +13,6 @@ var LocalSvmFacilitator = class {
13
13
  caipFamily = "solana:*";
14
14
  connection;
15
15
  constructor(rpcUrl) {
16
- console.log("[LocalSvmFacilitator] Initialized with RPC:", rpcUrl);
17
16
  this.connection = new Connection(rpcUrl, "confirmed");
18
17
  }
19
18
  /**
@@ -97,25 +96,18 @@ var LocalSvmFacilitator = class {
97
96
  getSigners(_network) {
98
97
  return [];
99
98
  }
100
- /**
101
- * Enable debug logging (disable in production)
102
- */
103
- debug = process.env.NODE_ENV === "development";
104
99
  /**
105
100
  * Verify a payment on-chain
106
101
  */
107
102
  async verify(payload, requirements) {
108
103
  try {
109
- const signature = payload.payload.signature;
104
+ const signature = payload.payload?.signature;
110
105
  if (!signature) {
111
106
  return { isValid: false, invalidReason: "Missing signature in payment payload" };
112
107
  }
113
108
  const payTo = requirements.payTo;
114
109
  const amountVal = requirements.amount || requirements.maxAmountRequired || "0";
115
110
  const requiredAmount = BigInt(amountVal);
116
- if (this.debug) {
117
- console.log(`[LocalSvmFacilitator] Verifying tx: ${signature.slice(0, 8)}...`);
118
- }
119
111
  const tx = await this.fetchTransactionWithRetry(signature, 3);
120
112
  if (!tx) {
121
113
  return { isValid: false, invalidReason: "Transaction not found or not confirmed" };
@@ -131,19 +123,8 @@ var LocalSvmFacilitator = class {
131
123
  if (!payer) payer = parsed.info.source;
132
124
  }
133
125
  }
134
- if ("program" in ix && (ix.program === "spl-token" || ix.program === "spl-token-2022")) {
135
- const parsed = ix.parsed;
136
- if (parsed?.type === "transferChecked" || parsed?.type === "transfer") {
137
- if (this.debug) {
138
- console.log(`[LocalSvmFacilitator] Found SPL transfer`);
139
- }
140
- }
141
- }
142
126
  }
143
127
  if (paidAmount >= requiredAmount) {
144
- if (this.debug) {
145
- console.log(`[LocalSvmFacilitator] Verification SUCCESS for tx: ${signature.slice(0, 8)}...`);
146
- }
147
128
  return {
148
129
  isValid: true,
149
130
  payer: payer || tx.transaction.message.accountKeys[0].pubkey.toBase58()
@@ -156,9 +137,6 @@ var LocalSvmFacilitator = class {
156
137
  };
157
138
  } catch (error) {
158
139
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
159
- if (this.debug) {
160
- console.error("[LocalSvmFacilitator] Verify error:", errorMessage);
161
- }
162
140
  throw new VerifyError(500, {
163
141
  isValid: false,
164
142
  invalidReason: errorMessage
@@ -13,7 +13,6 @@ var LocalSvmFacilitator = class {
13
13
  caipFamily = "solana:*";
14
14
  connection;
15
15
  constructor(rpcUrl) {
16
- console.log("[LocalSvmFacilitator] Initialized with RPC:", rpcUrl);
17
16
  this.connection = new web3_js.Connection(rpcUrl, "confirmed");
18
17
  }
19
18
  /**
@@ -97,25 +96,18 @@ var LocalSvmFacilitator = class {
97
96
  getSigners(_network) {
98
97
  return [];
99
98
  }
100
- /**
101
- * Enable debug logging (disable in production)
102
- */
103
- debug = process.env.NODE_ENV === "development";
104
99
  /**
105
100
  * Verify a payment on-chain
106
101
  */
107
102
  async verify(payload, requirements) {
108
103
  try {
109
- const signature = payload.payload.signature;
104
+ const signature = payload.payload?.signature;
110
105
  if (!signature) {
111
106
  return { isValid: false, invalidReason: "Missing signature in payment payload" };
112
107
  }
113
108
  const payTo = requirements.payTo;
114
109
  const amountVal = requirements.amount || requirements.maxAmountRequired || "0";
115
110
  const requiredAmount = BigInt(amountVal);
116
- if (this.debug) {
117
- console.log(`[LocalSvmFacilitator] Verifying tx: ${signature.slice(0, 8)}...`);
118
- }
119
111
  const tx = await this.fetchTransactionWithRetry(signature, 3);
120
112
  if (!tx) {
121
113
  return { isValid: false, invalidReason: "Transaction not found or not confirmed" };
@@ -131,19 +123,8 @@ var LocalSvmFacilitator = class {
131
123
  if (!payer) payer = parsed.info.source;
132
124
  }
133
125
  }
134
- if ("program" in ix && (ix.program === "spl-token" || ix.program === "spl-token-2022")) {
135
- const parsed = ix.parsed;
136
- if (parsed?.type === "transferChecked" || parsed?.type === "transfer") {
137
- if (this.debug) {
138
- console.log(`[LocalSvmFacilitator] Found SPL transfer`);
139
- }
140
- }
141
- }
142
126
  }
143
127
  if (paidAmount >= requiredAmount) {
144
- if (this.debug) {
145
- console.log(`[LocalSvmFacilitator] Verification SUCCESS for tx: ${signature.slice(0, 8)}...`);
146
- }
147
128
  return {
148
129
  isValid: true,
149
130
  payer: payer || tx.transaction.message.accountKeys[0].pubkey.toBase58()
@@ -156,9 +137,6 @@ var LocalSvmFacilitator = class {
156
137
  };
157
138
  } catch (error) {
158
139
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
159
- if (this.debug) {
160
- console.error("[LocalSvmFacilitator] Verify error:", errorMessage);
161
- }
162
140
  throw new types.VerifyError(500, {
163
141
  isValid: false,
164
142
  invalidReason: errorMessage
@@ -220,29 +198,98 @@ var LocalSvmFacilitator = class {
220
198
  };
221
199
 
222
200
  // src/next/index.ts
201
+ function transformPayAIToX402(payaiPayload, defaultNetwork) {
202
+ const { scheme, networkId, authorization } = payaiPayload;
203
+ const x402Scheme = scheme === "exact-svm" || scheme === "exact-evm" ? "exact" : scheme;
204
+ let network = defaultNetwork;
205
+ if (networkId === "solana") {
206
+ network = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
207
+ } else if (networkId === "solana-devnet") {
208
+ network = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
209
+ }
210
+ let signature;
211
+ if (scheme === "exact-svm" && "signatures" in authorization) {
212
+ signature = authorization.signatures?.[0];
213
+ }
214
+ return {
215
+ scheme: x402Scheme,
216
+ network,
217
+ payload: {
218
+ signature,
219
+ ...authorization
220
+ },
221
+ paymentDetails: payaiPayload.paymentDetails
222
+ };
223
+ }
223
224
  function createX402Middleware(config) {
225
+ const isLocalVerification = !!config.rpcUrl;
224
226
  let facilitatorClient;
225
- if (config.rpcUrl) {
227
+ if (isLocalVerification) {
226
228
  facilitatorClient = new LocalSvmFacilitator(config.rpcUrl);
227
229
  } else {
228
230
  const facilitatorUrl = config.facilitatorUrl || "https://x402.org/facilitator";
229
- facilitatorClient = new http.HTTPFacilitatorClient({
230
- url: facilitatorUrl
231
- });
231
+ facilitatorClient = new http.HTTPFacilitatorClient({ url: facilitatorUrl });
232
232
  }
233
233
  const server$2 = new server.x402ResourceServer(facilitatorClient);
234
234
  server$1.registerExactSvmScheme(server$2);
235
+ const networkId = config.network === "mainnet-beta" ? "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" : "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
235
236
  return function withMicropay(handler, routeConfig) {
237
+ const priceValue = config.price?.toString() || "0";
238
+ const amountValue = (BigInt(priceValue) * BigInt(1e6)).toString();
239
+ const paymentSpec = {
240
+ scheme: "exact",
241
+ payTo: config.walletAddress,
242
+ amount: amountValue,
243
+ network: networkId,
244
+ asset: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"
245
+ // Native SOL asset
246
+ };
236
247
  const finalConfig = routeConfig || {
237
248
  accepts: {
238
- scheme: "exact",
239
- payTo: config.walletAddress,
240
- price: config.price?.toString() || "0",
241
- network: config.network === "mainnet-beta" ? "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" : "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
249
+ ...paymentSpec,
250
+ price: priceValue
251
+ // Include for x402 SDK 402 generation
242
252
  }
243
253
  };
244
254
  const wrappedHandler = next.withX402(handler, finalConfig, server$2);
245
255
  return async (req, ctx) => {
256
+ const authHeader = req.headers?.get?.("authorization") || req.headers?.authorization;
257
+ if (authHeader && authHeader.toLowerCase().startsWith("x402 ")) {
258
+ try {
259
+ const base64Payload = authHeader.slice(5);
260
+ const payloadJson = Buffer.from(base64Payload, "base64").toString("utf8");
261
+ let payload = JSON.parse(payloadJson);
262
+ if (payload.scheme === "exact-svm" || payload.scheme === "exact-evm") {
263
+ payload = transformPayAIToX402(payload, networkId);
264
+ }
265
+ const signature = payload.payload?.signature;
266
+ if (signature) {
267
+ const verifyPaymentSpec = {
268
+ scheme: payload.scheme || "exact",
269
+ network: payload.network || networkId,
270
+ amount: amountValue,
271
+ payTo: config.walletAddress
272
+ };
273
+ let verifyResult;
274
+ try {
275
+ verifyResult = await facilitatorClient.verify(payload, verifyPaymentSpec);
276
+ } catch (facilitatorError) {
277
+ if (!isLocalVerification && config.rpcUrl) {
278
+ const localFacilitator = new LocalSvmFacilitator(config.rpcUrl);
279
+ verifyResult = await localFacilitator.verify(payload, verifyPaymentSpec);
280
+ } else {
281
+ throw facilitatorError;
282
+ }
283
+ }
284
+ if (verifyResult.isValid) {
285
+ const payerAddress = verifyResult.payer || "verified";
286
+ req.headers.set?.("x-payment-payer", payerAddress);
287
+ return await handler(req, ctx);
288
+ }
289
+ }
290
+ } catch (parseError) {
291
+ }
292
+ }
246
293
  const compatibleReq = new Proxy(req, {
247
294
  get(target, prop) {
248
295
  if (prop === "url") {
@@ -252,6 +299,10 @@ function createX402Middleware(config) {
252
299
  const headers = target.headers;
253
300
  return new Proxy(headers, {
254
301
  get(hTarget, hProp) {
302
+ if (hProp === "authorization" || hProp === "Authorization") {
303
+ const val3 = hTarget.get("authorization");
304
+ return val3;
305
+ }
255
306
  if (typeof hProp === "string" && !["get", "set", "has", "delete", "entries", "keys", "values", "forEach", "append"].includes(hProp) && typeof hTarget[hProp] === "undefined") {
256
307
  return hTarget.get(hProp) || void 0;
257
308
  }
@@ -264,7 +315,7 @@ function createX402Middleware(config) {
264
315
  return typeof val === "function" ? val.bind(target) : val;
265
316
  }
266
317
  });
267
- return wrappedHandler(compatibleReq, ctx);
318
+ return await wrappedHandler(compatibleReq, ctx);
268
319
  };
269
320
  };
270
321
  }
@@ -12,7 +12,6 @@ var LocalSvmFacilitator = class {
12
12
  caipFamily = "solana:*";
13
13
  connection;
14
14
  constructor(rpcUrl) {
15
- console.log("[LocalSvmFacilitator] Initialized with RPC:", rpcUrl);
16
15
  this.connection = new Connection(rpcUrl, "confirmed");
17
16
  }
18
17
  /**
@@ -96,25 +95,18 @@ var LocalSvmFacilitator = class {
96
95
  getSigners(_network) {
97
96
  return [];
98
97
  }
99
- /**
100
- * Enable debug logging (disable in production)
101
- */
102
- debug = process.env.NODE_ENV === "development";
103
98
  /**
104
99
  * Verify a payment on-chain
105
100
  */
106
101
  async verify(payload, requirements) {
107
102
  try {
108
- const signature = payload.payload.signature;
103
+ const signature = payload.payload?.signature;
109
104
  if (!signature) {
110
105
  return { isValid: false, invalidReason: "Missing signature in payment payload" };
111
106
  }
112
107
  const payTo = requirements.payTo;
113
108
  const amountVal = requirements.amount || requirements.maxAmountRequired || "0";
114
109
  const requiredAmount = BigInt(amountVal);
115
- if (this.debug) {
116
- console.log(`[LocalSvmFacilitator] Verifying tx: ${signature.slice(0, 8)}...`);
117
- }
118
110
  const tx = await this.fetchTransactionWithRetry(signature, 3);
119
111
  if (!tx) {
120
112
  return { isValid: false, invalidReason: "Transaction not found or not confirmed" };
@@ -130,19 +122,8 @@ var LocalSvmFacilitator = class {
130
122
  if (!payer) payer = parsed.info.source;
131
123
  }
132
124
  }
133
- if ("program" in ix && (ix.program === "spl-token" || ix.program === "spl-token-2022")) {
134
- const parsed = ix.parsed;
135
- if (parsed?.type === "transferChecked" || parsed?.type === "transfer") {
136
- if (this.debug) {
137
- console.log(`[LocalSvmFacilitator] Found SPL transfer`);
138
- }
139
- }
140
- }
141
125
  }
142
126
  if (paidAmount >= requiredAmount) {
143
- if (this.debug) {
144
- console.log(`[LocalSvmFacilitator] Verification SUCCESS for tx: ${signature.slice(0, 8)}...`);
145
- }
146
127
  return {
147
128
  isValid: true,
148
129
  payer: payer || tx.transaction.message.accountKeys[0].pubkey.toBase58()
@@ -155,9 +136,6 @@ var LocalSvmFacilitator = class {
155
136
  };
156
137
  } catch (error) {
157
138
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
158
- if (this.debug) {
159
- console.error("[LocalSvmFacilitator] Verify error:", errorMessage);
160
- }
161
139
  throw new VerifyError(500, {
162
140
  isValid: false,
163
141
  invalidReason: errorMessage
@@ -219,29 +197,98 @@ var LocalSvmFacilitator = class {
219
197
  };
220
198
 
221
199
  // src/next/index.ts
200
+ function transformPayAIToX402(payaiPayload, defaultNetwork) {
201
+ const { scheme, networkId, authorization } = payaiPayload;
202
+ const x402Scheme = scheme === "exact-svm" || scheme === "exact-evm" ? "exact" : scheme;
203
+ let network = defaultNetwork;
204
+ if (networkId === "solana") {
205
+ network = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
206
+ } else if (networkId === "solana-devnet") {
207
+ network = "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
208
+ }
209
+ let signature;
210
+ if (scheme === "exact-svm" && "signatures" in authorization) {
211
+ signature = authorization.signatures?.[0];
212
+ }
213
+ return {
214
+ scheme: x402Scheme,
215
+ network,
216
+ payload: {
217
+ signature,
218
+ ...authorization
219
+ },
220
+ paymentDetails: payaiPayload.paymentDetails
221
+ };
222
+ }
222
223
  function createX402Middleware(config) {
224
+ const isLocalVerification = !!config.rpcUrl;
223
225
  let facilitatorClient;
224
- if (config.rpcUrl) {
226
+ if (isLocalVerification) {
225
227
  facilitatorClient = new LocalSvmFacilitator(config.rpcUrl);
226
228
  } else {
227
229
  const facilitatorUrl = config.facilitatorUrl || "https://x402.org/facilitator";
228
- facilitatorClient = new HTTPFacilitatorClient({
229
- url: facilitatorUrl
230
- });
230
+ facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl });
231
231
  }
232
232
  const server = new x402ResourceServer(facilitatorClient);
233
233
  registerExactSvmScheme(server);
234
+ const networkId = config.network === "mainnet-beta" ? "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" : "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1";
234
235
  return function withMicropay(handler, routeConfig) {
236
+ const priceValue = config.price?.toString() || "0";
237
+ const amountValue = (BigInt(priceValue) * BigInt(1e6)).toString();
238
+ const paymentSpec = {
239
+ scheme: "exact",
240
+ payTo: config.walletAddress,
241
+ amount: amountValue,
242
+ network: networkId,
243
+ asset: "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"
244
+ // Native SOL asset
245
+ };
235
246
  const finalConfig = routeConfig || {
236
247
  accepts: {
237
- scheme: "exact",
238
- payTo: config.walletAddress,
239
- price: config.price?.toString() || "0",
240
- network: config.network === "mainnet-beta" ? "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" : "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1"
248
+ ...paymentSpec,
249
+ price: priceValue
250
+ // Include for x402 SDK 402 generation
241
251
  }
242
252
  };
243
253
  const wrappedHandler = withX402$1(handler, finalConfig, server);
244
254
  return async (req, ctx) => {
255
+ const authHeader = req.headers?.get?.("authorization") || req.headers?.authorization;
256
+ if (authHeader && authHeader.toLowerCase().startsWith("x402 ")) {
257
+ try {
258
+ const base64Payload = authHeader.slice(5);
259
+ const payloadJson = Buffer.from(base64Payload, "base64").toString("utf8");
260
+ let payload = JSON.parse(payloadJson);
261
+ if (payload.scheme === "exact-svm" || payload.scheme === "exact-evm") {
262
+ payload = transformPayAIToX402(payload, networkId);
263
+ }
264
+ const signature = payload.payload?.signature;
265
+ if (signature) {
266
+ const verifyPaymentSpec = {
267
+ scheme: payload.scheme || "exact",
268
+ network: payload.network || networkId,
269
+ amount: amountValue,
270
+ payTo: config.walletAddress
271
+ };
272
+ let verifyResult;
273
+ try {
274
+ verifyResult = await facilitatorClient.verify(payload, verifyPaymentSpec);
275
+ } catch (facilitatorError) {
276
+ if (!isLocalVerification && config.rpcUrl) {
277
+ const localFacilitator = new LocalSvmFacilitator(config.rpcUrl);
278
+ verifyResult = await localFacilitator.verify(payload, verifyPaymentSpec);
279
+ } else {
280
+ throw facilitatorError;
281
+ }
282
+ }
283
+ if (verifyResult.isValid) {
284
+ const payerAddress = verifyResult.payer || "verified";
285
+ req.headers.set?.("x-payment-payer", payerAddress);
286
+ return await handler(req, ctx);
287
+ }
288
+ }
289
+ } catch (parseError) {
290
+ }
291
+ }
245
292
  const compatibleReq = new Proxy(req, {
246
293
  get(target, prop) {
247
294
  if (prop === "url") {
@@ -251,6 +298,10 @@ function createX402Middleware(config) {
251
298
  const headers = target.headers;
252
299
  return new Proxy(headers, {
253
300
  get(hTarget, hProp) {
301
+ if (hProp === "authorization" || hProp === "Authorization") {
302
+ const val3 = hTarget.get("authorization");
303
+ return val3;
304
+ }
254
305
  if (typeof hProp === "string" && !["get", "set", "has", "delete", "entries", "keys", "values", "forEach", "append"].includes(hProp) && typeof hTarget[hProp] === "undefined") {
255
306
  return hTarget.get(hProp) || void 0;
256
307
  }
@@ -263,7 +314,7 @@ function createX402Middleware(config) {
263
314
  return typeof val === "function" ? val.bind(target) : val;
264
315
  }
265
316
  });
266
- return wrappedHandler(compatibleReq, ctx);
317
+ return await wrappedHandler(compatibleReq, ctx);
267
318
  };
268
319
  };
269
320
  }
@@ -1,4 +1,5 @@
1
- import { S as SessionConfig, a as SessionData, b as SessionValidation } from '../types-BWYQMw03.cjs';
1
+ import { S as SessionConfig, a as SessionData, b as SessionValidation } from '../types-BfKfgout.cjs';
2
+ export { c as SessionJWTPayload } from '../types-BfKfgout.cjs';
2
3
 
3
4
  /**
4
5
  * Create a new session after successful payment
@@ -26,4 +27,4 @@ declare function addArticleToSession(token: string, articleId: string, secret: s
26
27
  */
27
28
  declare function isArticleUnlocked(token: string, articleId: string, secret: string): Promise<boolean>;
28
29
 
29
- export { addArticleToSession, createSession, isArticleUnlocked, validateSession };
30
+ export { SessionConfig, SessionData, SessionValidation, addArticleToSession, createSession, isArticleUnlocked, validateSession };
@@ -1,4 +1,5 @@
1
- import { S as SessionConfig, a as SessionData, b as SessionValidation } from '../types-BWYQMw03.js';
1
+ import { S as SessionConfig, a as SessionData, b as SessionValidation } from '../types-BfKfgout.js';
2
+ export { c as SessionJWTPayload } from '../types-BfKfgout.js';
2
3
 
3
4
  /**
4
5
  * Create a new session after successful payment
@@ -26,4 +27,4 @@ declare function addArticleToSession(token: string, articleId: string, secret: s
26
27
  */
27
28
  declare function isArticleUnlocked(token: string, articleId: string, secret: string): Promise<boolean>;
28
29
 
29
- export { addArticleToSession, createSession, isArticleUnlocked, validateSession };
30
+ export { SessionConfig, SessionData, SessionValidation, addArticleToSession, createSession, isArticleUnlocked, validateSession };
@@ -29,5 +29,20 @@ interface SessionValidation {
29
29
  /** Reason for invalid session */
30
30
  reason?: string;
31
31
  }
32
+ /** JWT payload structure for sessions */
33
+ interface SessionJWTPayload {
34
+ /** Wallet address (subject) */
35
+ sub: string;
36
+ /** Session ID */
37
+ sid: string;
38
+ /** Unlocked article IDs */
39
+ articles: string[];
40
+ /** Site-wide unlock flag */
41
+ siteWide: boolean;
42
+ /** Issued at timestamp */
43
+ iat: number;
44
+ /** Expiration timestamp */
45
+ exp: number;
46
+ }
32
47
 
33
- export type { SessionConfig as S, SessionData as a, SessionValidation as b };
48
+ export type { SessionConfig as S, SessionData as a, SessionValidation as b, SessionJWTPayload as c };
@@ -29,5 +29,20 @@ interface SessionValidation {
29
29
  /** Reason for invalid session */
30
30
  reason?: string;
31
31
  }
32
+ /** JWT payload structure for sessions */
33
+ interface SessionJWTPayload {
34
+ /** Wallet address (subject) */
35
+ sub: string;
36
+ /** Session ID */
37
+ sid: string;
38
+ /** Unlocked article IDs */
39
+ articles: string[];
40
+ /** Site-wide unlock flag */
41
+ siteWide: boolean;
42
+ /** Issued at timestamp */
43
+ iat: number;
44
+ /** Expiration timestamp */
45
+ exp: number;
46
+ }
32
47
 
33
- export type { SessionConfig as S, SessionData as a, SessionValidation as b };
48
+ export type { SessionConfig as S, SessionData as a, SessionValidation as b, SessionJWTPayload as c };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alleyboss/micropay-solana-x402-paywall",
3
- "version": "3.3.11",
3
+ "version": "3.3.13",
4
4
  "description": "Production-ready Solana micropayments library wrapper for official x402 SDK",
5
5
  "author": "AlleyBoss",
6
6
  "license": "MIT",