@alleyboss/micropay-solana-x402-paywall 3.0.6 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -106,10 +106,65 @@ import { createSession, validateSession } from '@alleyboss/micropay-solana-x402-
106
106
  import { createPaymentFlow } from '@alleyboss/micropay-solana-x402-paywall/client';
107
107
  ```
108
108
 
109
+ ## 🛡️ Self-Sovereign Verification (New in v3.1)
110
+
111
+ By default, the library uses the `x402.org` hosted facilitator for convenience. However, you can opt for **Self-Sovereign Mode** to verify payments directly against your own Solana RPC node, removing reliance on any external API services.
112
+
113
+ ```typescript
114
+ // app/api/articles/[id]/route.ts
115
+ const withMicropay = createX402Middleware({
116
+ walletAddress: 'YOUR_WALLET',
117
+ network: 'devnet',
118
+ price: '1000000',
119
+ // ⚡️ Enable Self-Sovereign Mode
120
+ // The library will verify transactions locally using this RPC connection.
121
+ rpcUrl: process.env.NEXT_PUBLIC_RPC_URL
122
+ });
123
+ ### 🛡️ Verification Flow (Self-Sovereign Mode)
124
+
125
+ ```mermaid
126
+ sequenceDiagram
127
+ participant User
128
+ participant App
129
+ participant Lib as x402 Lib
130
+ participant RPC as Solana RPC
131
+
132
+ User->>App: Request Premium Content
133
+ App->>Lib: Create Payment Options
134
+ Lib-->>User: Return 402 + Payment Link
135
+ User->>RPC: Submit Transaction
136
+ User->>App: Send Receipt/Signature
137
+ App->>Lib: Verify Transaction
138
+ Lib->>RPC: Get Transaction Status (Local)
139
+ RPC-->>Lib: Confirmed
140
+ Lib-->>App: Valid Session Token
141
+ App-->>User: Unlock Content
142
+ ```
143
+
144
+ ### 🆚 Hosted vs. Self-Sovereign Mode
145
+
146
+ | Feature | Hosted Mode (Default) | Self-Sovereign Mode |
147
+ |---------|----------------------|---------------------|
148
+ | **Verification** | Verified by x402.org | Verified by **You** (Local RPC) |
149
+ | **Trust** | Trust x402 Facilitator | Trustless / Trust Your Node |
150
+ | **Privacy** | Metadata sent to facilitator | No external data sharing |
151
+ | **Setup** | Zero-config | Requires RPC URL |
152
+ | **Best For** | Quick startups, MVPs | Production, High-Volume, Agents |
153
+
109
154
  ## 🤖 AI Agent Payments
110
155
 
111
156
  Enable autonomous AI agents to pay for premium API access.
112
157
 
158
+ ```mermaid
159
+ flowchart LR
160
+ A[AI Agent] -->|1. Detects Paywall| B(Check Wallet)
161
+ B -->|2. Sufficient Balance?| C{Pay?}
162
+ C -- Yes --> D[Sign & Send Tx]
163
+ D --> E[Wait for Confirmation]
164
+ E -->|3. Success| F[Retry Request + Proof]
165
+ F --> G((Unlock Data))
166
+ ```
167
+
113
168
  ```typescript
114
169
  import { executeAgentPayment } from '@alleyboss/micropay-solana-x402-paywall/agent';
115
170
  import { Keypair, Connection } from '@solana/web3.js';
@@ -121,7 +176,7 @@ const result = await executeAgentPayment({
121
176
  agentKeypair,
122
177
  recipientAddress: 'CREATOR_WALLET',
123
178
  amountLamports: 2_000_000n,
124
- priorityFee: { enabled: true, microLamports: 10000 }, // Priority Fees Supported
179
+ priorityFee: { enabled: true, microLamports: 10000 },
125
180
  });
126
181
 
127
182
  if (result.success) {
@@ -4,21 +4,161 @@ var next = require('@x402/next');
4
4
  var server = require('@x402/core/server');
5
5
  var http = require('@x402/core/http');
6
6
  var server$1 = require('@x402/svm/exact/server');
7
+ var web3_js = require('@solana/web3.js');
8
+ var types = require('@x402/core/types');
9
+
10
+ // src/next/index.ts
11
+ var LocalSvmFacilitator = class {
12
+ scheme = "exact";
13
+ caipFamily = "solana:*";
14
+ connection;
15
+ constructor(rpcUrl) {
16
+ this.connection = new web3_js.Connection(rpcUrl, "confirmed");
17
+ }
18
+ /**
19
+ * Get supported payment kinds
20
+ * Mocking the response of the /supported endpoint
21
+ */
22
+ async getSupported(extensionKeys = []) {
23
+ return {
24
+ kinds: [
25
+ {
26
+ x402Version: 1,
27
+ scheme: "exact",
28
+ network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
29
+ // Devnet
30
+ extra: {}
31
+ },
32
+ {
33
+ x402Version: 1,
34
+ scheme: "exact",
35
+ network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
36
+ // Mainnet
37
+ extra: {}
38
+ }
39
+ ],
40
+ extensions: [],
41
+ signers: {
42
+ "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1": [],
43
+ "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp": []
44
+ }
45
+ };
46
+ }
47
+ /**
48
+ * Get mechanism-specific extra data
49
+ */
50
+ getExtra(network) {
51
+ return void 0;
52
+ }
53
+ /**
54
+ * Get default signers (not used for local verification usually, but required by interface)
55
+ */
56
+ getSigners(network) {
57
+ return [];
58
+ }
59
+ /**
60
+ * Verify a payment on-chain
61
+ */
62
+ async verify(payload, requirements) {
63
+ try {
64
+ const signature = payload.payload.signature;
65
+ if (!signature) {
66
+ return { isValid: false, invalidReason: "Missing signature in payment payload" };
67
+ }
68
+ const payTo = requirements.payTo;
69
+ const amountVal = requirements.amount || requirements.maxAmountRequired || "0";
70
+ const requiredAmount = BigInt(amountVal);
71
+ console.log(`[LocalSvmFacilitator] Verifying signature: ${signature}`);
72
+ console.log(`[LocalSvmFacilitator] Required Amount: ${requiredAmount}, PayTo: ${payTo}`);
73
+ const tx = await this.connection.getParsedTransaction(signature, {
74
+ maxSupportedTransactionVersion: 0,
75
+ commitment: "confirmed"
76
+ });
77
+ if (!tx) {
78
+ console.error("[LocalSvmFacilitator] Transaction not found or not confirmed");
79
+ return { isValid: false, invalidReason: "Transaction not found or not confirmed" };
80
+ }
81
+ console.log("[LocalSvmFacilitator] Transaction found. Parsing instructions...");
82
+ const instructions = tx.transaction.message.instructions;
83
+ let paidAmount = 0n;
84
+ let payer = void 0;
85
+ for (const ix of instructions) {
86
+ if ("program" in ix && ix.program === "system") {
87
+ const parsed = ix.parsed;
88
+ if (parsed.type === "transfer") {
89
+ const info = parsed.info;
90
+ console.log(`[LocalSvmFacilitator] Found transfer: ${info.lamports} lamports to ${info.destination}`);
91
+ if (info.destination === payTo) {
92
+ paidAmount += BigInt(info.lamports);
93
+ if (!payer) payer = info.source;
94
+ }
95
+ }
96
+ }
97
+ }
98
+ console.log(`[LocalSvmFacilitator] Total Paid Correctly: ${paidAmount}`);
99
+ if (paidAmount >= requiredAmount) {
100
+ console.log("[LocalSvmFacilitator] Verification SUCCESS");
101
+ return {
102
+ isValid: true,
103
+ payer: payer || tx.transaction.message.accountKeys[0].pubkey.toBase58()
104
+ };
105
+ }
106
+ console.error(`[LocalSvmFacilitator] Verification FAILED. Paid: ${paidAmount}, Required: ${requiredAmount}`);
107
+ return {
108
+ isValid: false,
109
+ invalidReason: `Insufficient payment. Required: ${requiredAmount}, Found: ${paidAmount}`,
110
+ payer
111
+ };
112
+ } catch (error) {
113
+ console.error("[LocalSvmFacilitator] Verify error:", error);
114
+ throw new types.VerifyError(500, {
115
+ isValid: false,
116
+ invalidReason: error.message
117
+ });
118
+ }
119
+ }
120
+ /**
121
+ * Settle a payment (not applicable for direct chain verification, usually)
122
+ * But we must implement it. For 'exact', settlement is just verification + finality.
123
+ */
124
+ async settle(payload, requirements) {
125
+ const verifyResult = await this.verify(payload, requirements);
126
+ if (!verifyResult.isValid) {
127
+ throw new types.SettleError(400, {
128
+ success: false,
129
+ errorReason: verifyResult.invalidReason || "Verification failed",
130
+ transaction: payload.payload.signature,
131
+ network: requirements.network
132
+ });
133
+ }
134
+ return {
135
+ success: true,
136
+ payer: verifyResult.payer,
137
+ transaction: payload.payload.signature,
138
+ network: requirements.network
139
+ };
140
+ }
141
+ };
7
142
 
8
143
  // src/next/index.ts
9
144
  function createX402Middleware(config) {
10
- const facilitatorUrl = config.facilitatorUrl || "https://x402.org/facilitator";
11
- const client = new http.HTTPFacilitatorClient({
12
- url: facilitatorUrl
13
- });
14
- const server$2 = new server.x402ResourceServer(client);
15
- server$1.registerExactSvmScheme(server$2, {});
145
+ let facilitatorClient;
146
+ if (config.rpcUrl) {
147
+ facilitatorClient = new LocalSvmFacilitator(config.rpcUrl);
148
+ } else {
149
+ const facilitatorUrl = config.facilitatorUrl || "https://x402.org/facilitator";
150
+ facilitatorClient = new http.HTTPFacilitatorClient({
151
+ url: facilitatorUrl
152
+ });
153
+ }
154
+ const server$2 = new server.x402ResourceServer(facilitatorClient);
155
+ server$1.registerExactSvmScheme(server$2);
16
156
  return function withMicropay(handler, routeConfig) {
17
157
  const finalConfig = routeConfig || {
18
158
  accepts: {
19
159
  scheme: "exact",
20
160
  payTo: config.walletAddress,
21
- maxAmountRequired: config.price?.toString() || "0",
161
+ amount: config.price?.toString() || "0",
22
162
  network: config.network === "mainnet-beta" ? "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" : "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
23
163
  asset: "native"
24
164
  }
@@ -14,6 +14,8 @@ interface X402Config {
14
14
  price?: string | number;
15
15
  /** Network (mainnet-beta or devnet) */
16
16
  network?: 'mainnet-beta' | 'devnet';
17
+ /** RPC URL for local verification (optional, enables self-contained validation) */
18
+ rpcUrl?: string;
17
19
  }
18
20
  /**
19
21
  * Create a specialized Next.js middleware with Solana support pre-configured
@@ -14,6 +14,8 @@ interface X402Config {
14
14
  price?: string | number;
15
15
  /** Network (mainnet-beta or devnet) */
16
16
  network?: 'mainnet-beta' | 'devnet';
17
+ /** RPC URL for local verification (optional, enables self-contained validation) */
18
+ rpcUrl?: string;
17
19
  }
18
20
  /**
19
21
  * Create a specialized Next.js middleware with Solana support pre-configured
@@ -3,21 +3,161 @@ import { x402ResourceServer } from '@x402/core/server';
3
3
  export { x402ResourceServer } from '@x402/core/server';
4
4
  import { HTTPFacilitatorClient } from '@x402/core/http';
5
5
  import { registerExactSvmScheme } from '@x402/svm/exact/server';
6
+ import { Connection } from '@solana/web3.js';
7
+ import { VerifyError, SettleError } from '@x402/core/types';
8
+
9
+ // src/next/index.ts
10
+ var LocalSvmFacilitator = class {
11
+ scheme = "exact";
12
+ caipFamily = "solana:*";
13
+ connection;
14
+ constructor(rpcUrl) {
15
+ this.connection = new Connection(rpcUrl, "confirmed");
16
+ }
17
+ /**
18
+ * Get supported payment kinds
19
+ * Mocking the response of the /supported endpoint
20
+ */
21
+ async getSupported(extensionKeys = []) {
22
+ return {
23
+ kinds: [
24
+ {
25
+ x402Version: 1,
26
+ scheme: "exact",
27
+ network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
28
+ // Devnet
29
+ extra: {}
30
+ },
31
+ {
32
+ x402Version: 1,
33
+ scheme: "exact",
34
+ network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
35
+ // Mainnet
36
+ extra: {}
37
+ }
38
+ ],
39
+ extensions: [],
40
+ signers: {
41
+ "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1": [],
42
+ "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp": []
43
+ }
44
+ };
45
+ }
46
+ /**
47
+ * Get mechanism-specific extra data
48
+ */
49
+ getExtra(network) {
50
+ return void 0;
51
+ }
52
+ /**
53
+ * Get default signers (not used for local verification usually, but required by interface)
54
+ */
55
+ getSigners(network) {
56
+ return [];
57
+ }
58
+ /**
59
+ * Verify a payment on-chain
60
+ */
61
+ async verify(payload, requirements) {
62
+ try {
63
+ const signature = payload.payload.signature;
64
+ if (!signature) {
65
+ return { isValid: false, invalidReason: "Missing signature in payment payload" };
66
+ }
67
+ const payTo = requirements.payTo;
68
+ const amountVal = requirements.amount || requirements.maxAmountRequired || "0";
69
+ const requiredAmount = BigInt(amountVal);
70
+ console.log(`[LocalSvmFacilitator] Verifying signature: ${signature}`);
71
+ console.log(`[LocalSvmFacilitator] Required Amount: ${requiredAmount}, PayTo: ${payTo}`);
72
+ const tx = await this.connection.getParsedTransaction(signature, {
73
+ maxSupportedTransactionVersion: 0,
74
+ commitment: "confirmed"
75
+ });
76
+ if (!tx) {
77
+ console.error("[LocalSvmFacilitator] Transaction not found or not confirmed");
78
+ return { isValid: false, invalidReason: "Transaction not found or not confirmed" };
79
+ }
80
+ console.log("[LocalSvmFacilitator] Transaction found. Parsing instructions...");
81
+ const instructions = tx.transaction.message.instructions;
82
+ let paidAmount = 0n;
83
+ let payer = void 0;
84
+ for (const ix of instructions) {
85
+ if ("program" in ix && ix.program === "system") {
86
+ const parsed = ix.parsed;
87
+ if (parsed.type === "transfer") {
88
+ const info = parsed.info;
89
+ console.log(`[LocalSvmFacilitator] Found transfer: ${info.lamports} lamports to ${info.destination}`);
90
+ if (info.destination === payTo) {
91
+ paidAmount += BigInt(info.lamports);
92
+ if (!payer) payer = info.source;
93
+ }
94
+ }
95
+ }
96
+ }
97
+ console.log(`[LocalSvmFacilitator] Total Paid Correctly: ${paidAmount}`);
98
+ if (paidAmount >= requiredAmount) {
99
+ console.log("[LocalSvmFacilitator] Verification SUCCESS");
100
+ return {
101
+ isValid: true,
102
+ payer: payer || tx.transaction.message.accountKeys[0].pubkey.toBase58()
103
+ };
104
+ }
105
+ console.error(`[LocalSvmFacilitator] Verification FAILED. Paid: ${paidAmount}, Required: ${requiredAmount}`);
106
+ return {
107
+ isValid: false,
108
+ invalidReason: `Insufficient payment. Required: ${requiredAmount}, Found: ${paidAmount}`,
109
+ payer
110
+ };
111
+ } catch (error) {
112
+ console.error("[LocalSvmFacilitator] Verify error:", error);
113
+ throw new VerifyError(500, {
114
+ isValid: false,
115
+ invalidReason: error.message
116
+ });
117
+ }
118
+ }
119
+ /**
120
+ * Settle a payment (not applicable for direct chain verification, usually)
121
+ * But we must implement it. For 'exact', settlement is just verification + finality.
122
+ */
123
+ async settle(payload, requirements) {
124
+ const verifyResult = await this.verify(payload, requirements);
125
+ if (!verifyResult.isValid) {
126
+ throw new SettleError(400, {
127
+ success: false,
128
+ errorReason: verifyResult.invalidReason || "Verification failed",
129
+ transaction: payload.payload.signature,
130
+ network: requirements.network
131
+ });
132
+ }
133
+ return {
134
+ success: true,
135
+ payer: verifyResult.payer,
136
+ transaction: payload.payload.signature,
137
+ network: requirements.network
138
+ };
139
+ }
140
+ };
6
141
 
7
142
  // src/next/index.ts
8
143
  function createX402Middleware(config) {
9
- const facilitatorUrl = config.facilitatorUrl || "https://x402.org/facilitator";
10
- const client = new HTTPFacilitatorClient({
11
- url: facilitatorUrl
12
- });
13
- const server = new x402ResourceServer(client);
14
- registerExactSvmScheme(server, {});
144
+ let facilitatorClient;
145
+ if (config.rpcUrl) {
146
+ facilitatorClient = new LocalSvmFacilitator(config.rpcUrl);
147
+ } else {
148
+ const facilitatorUrl = config.facilitatorUrl || "https://x402.org/facilitator";
149
+ facilitatorClient = new HTTPFacilitatorClient({
150
+ url: facilitatorUrl
151
+ });
152
+ }
153
+ const server = new x402ResourceServer(facilitatorClient);
154
+ registerExactSvmScheme(server);
15
155
  return function withMicropay(handler, routeConfig) {
16
156
  const finalConfig = routeConfig || {
17
157
  accepts: {
18
158
  scheme: "exact",
19
159
  payTo: config.walletAddress,
20
- maxAmountRequired: config.price?.toString() || "0",
160
+ amount: config.price?.toString() || "0",
21
161
  network: config.network === "mainnet-beta" ? "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" : "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
22
162
  asset: "native"
23
163
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alleyboss/micropay-solana-x402-paywall",
3
- "version": "3.0.6",
3
+ "version": "3.1.1",
4
4
  "description": "Production-ready Solana micropayments library wrapper for official x402 SDK",
5
5
  "author": "AlleyBoss",
6
6
  "license": "MIT",