@alleyboss/micropay-solana-x402-paywall 3.0.6 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/next/index.cjs +137 -6
- package/dist/next/index.d.cts +2 -0
- package/dist/next/index.d.ts +2 -0
- package/dist/next/index.js +137 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -106,6 +106,22 @@ 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
|
+
```
|
|
124
|
+
|
|
109
125
|
## 🤖 AI Agent Payments
|
|
110
126
|
|
|
111
127
|
Enable autonomous AI agents to pay for premium API access.
|
package/dist/next/index.cjs
CHANGED
|
@@ -4,15 +4,146 @@ 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 tx = await this.connection.getParsedTransaction(signature, {
|
|
69
|
+
maxSupportedTransactionVersion: 0,
|
|
70
|
+
commitment: "confirmed"
|
|
71
|
+
});
|
|
72
|
+
if (!tx) {
|
|
73
|
+
return { isValid: false, invalidReason: "Transaction not found or not confirmed" };
|
|
74
|
+
}
|
|
75
|
+
const payTo = requirements.payTo;
|
|
76
|
+
const requiredAmount = BigInt(requirements.amount);
|
|
77
|
+
const instructions = tx.transaction.message.instructions;
|
|
78
|
+
let paidAmount = 0n;
|
|
79
|
+
let payer = void 0;
|
|
80
|
+
for (const ix of instructions) {
|
|
81
|
+
if ("program" in ix && ix.program === "system") {
|
|
82
|
+
const parsed = ix.parsed;
|
|
83
|
+
if (parsed.type === "transfer") {
|
|
84
|
+
const info = parsed.info;
|
|
85
|
+
if (info.destination === payTo) {
|
|
86
|
+
paidAmount += BigInt(info.lamports);
|
|
87
|
+
if (!payer) payer = info.source;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (paidAmount >= requiredAmount) {
|
|
93
|
+
return {
|
|
94
|
+
isValid: true,
|
|
95
|
+
payer: payer || tx.transaction.message.accountKeys[0].pubkey.toBase58()
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
isValid: false,
|
|
100
|
+
invalidReason: `Insufficient payment. Required: ${requiredAmount}, Found: ${paidAmount}`,
|
|
101
|
+
payer
|
|
102
|
+
};
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error("[LocalSvmFacilitator] Verify error:", error);
|
|
105
|
+
throw new types.VerifyError(500, {
|
|
106
|
+
isValid: false,
|
|
107
|
+
invalidReason: error.message
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Settle a payment (not applicable for direct chain verification, usually)
|
|
113
|
+
* But we must implement it. For 'exact', settlement is just verification + finality.
|
|
114
|
+
*/
|
|
115
|
+
async settle(payload, requirements) {
|
|
116
|
+
const verifyResult = await this.verify(payload, requirements);
|
|
117
|
+
if (!verifyResult.isValid) {
|
|
118
|
+
throw new types.SettleError(400, {
|
|
119
|
+
success: false,
|
|
120
|
+
errorReason: verifyResult.invalidReason || "Verification failed",
|
|
121
|
+
transaction: payload.payload.signature,
|
|
122
|
+
network: requirements.network
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
success: true,
|
|
127
|
+
payer: verifyResult.payer,
|
|
128
|
+
transaction: payload.payload.signature,
|
|
129
|
+
network: requirements.network
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
};
|
|
7
133
|
|
|
8
134
|
// src/next/index.ts
|
|
9
135
|
function createX402Middleware(config) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
136
|
+
let facilitatorClient;
|
|
137
|
+
if (config.rpcUrl) {
|
|
138
|
+
facilitatorClient = new LocalSvmFacilitator(config.rpcUrl);
|
|
139
|
+
} else {
|
|
140
|
+
const facilitatorUrl = config.facilitatorUrl || "https://x402.org/facilitator";
|
|
141
|
+
facilitatorClient = new http.HTTPFacilitatorClient({
|
|
142
|
+
url: facilitatorUrl
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
const server$2 = new server.x402ResourceServer(facilitatorClient);
|
|
146
|
+
server$1.registerExactSvmScheme(server$2);
|
|
16
147
|
return function withMicropay(handler, routeConfig) {
|
|
17
148
|
const finalConfig = routeConfig || {
|
|
18
149
|
accepts: {
|
package/dist/next/index.d.cts
CHANGED
|
@@ -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
|
package/dist/next/index.d.ts
CHANGED
|
@@ -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
|
package/dist/next/index.js
CHANGED
|
@@ -3,15 +3,146 @@ 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 tx = await this.connection.getParsedTransaction(signature, {
|
|
68
|
+
maxSupportedTransactionVersion: 0,
|
|
69
|
+
commitment: "confirmed"
|
|
70
|
+
});
|
|
71
|
+
if (!tx) {
|
|
72
|
+
return { isValid: false, invalidReason: "Transaction not found or not confirmed" };
|
|
73
|
+
}
|
|
74
|
+
const payTo = requirements.payTo;
|
|
75
|
+
const requiredAmount = BigInt(requirements.amount);
|
|
76
|
+
const instructions = tx.transaction.message.instructions;
|
|
77
|
+
let paidAmount = 0n;
|
|
78
|
+
let payer = void 0;
|
|
79
|
+
for (const ix of instructions) {
|
|
80
|
+
if ("program" in ix && ix.program === "system") {
|
|
81
|
+
const parsed = ix.parsed;
|
|
82
|
+
if (parsed.type === "transfer") {
|
|
83
|
+
const info = parsed.info;
|
|
84
|
+
if (info.destination === payTo) {
|
|
85
|
+
paidAmount += BigInt(info.lamports);
|
|
86
|
+
if (!payer) payer = info.source;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (paidAmount >= requiredAmount) {
|
|
92
|
+
return {
|
|
93
|
+
isValid: true,
|
|
94
|
+
payer: payer || tx.transaction.message.accountKeys[0].pubkey.toBase58()
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
isValid: false,
|
|
99
|
+
invalidReason: `Insufficient payment. Required: ${requiredAmount}, Found: ${paidAmount}`,
|
|
100
|
+
payer
|
|
101
|
+
};
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error("[LocalSvmFacilitator] Verify error:", error);
|
|
104
|
+
throw new VerifyError(500, {
|
|
105
|
+
isValid: false,
|
|
106
|
+
invalidReason: error.message
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Settle a payment (not applicable for direct chain verification, usually)
|
|
112
|
+
* But we must implement it. For 'exact', settlement is just verification + finality.
|
|
113
|
+
*/
|
|
114
|
+
async settle(payload, requirements) {
|
|
115
|
+
const verifyResult = await this.verify(payload, requirements);
|
|
116
|
+
if (!verifyResult.isValid) {
|
|
117
|
+
throw new SettleError(400, {
|
|
118
|
+
success: false,
|
|
119
|
+
errorReason: verifyResult.invalidReason || "Verification failed",
|
|
120
|
+
transaction: payload.payload.signature,
|
|
121
|
+
network: requirements.network
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
success: true,
|
|
126
|
+
payer: verifyResult.payer,
|
|
127
|
+
transaction: payload.payload.signature,
|
|
128
|
+
network: requirements.network
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
};
|
|
6
132
|
|
|
7
133
|
// src/next/index.ts
|
|
8
134
|
function createX402Middleware(config) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
135
|
+
let facilitatorClient;
|
|
136
|
+
if (config.rpcUrl) {
|
|
137
|
+
facilitatorClient = new LocalSvmFacilitator(config.rpcUrl);
|
|
138
|
+
} else {
|
|
139
|
+
const facilitatorUrl = config.facilitatorUrl || "https://x402.org/facilitator";
|
|
140
|
+
facilitatorClient = new HTTPFacilitatorClient({
|
|
141
|
+
url: facilitatorUrl
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
const server = new x402ResourceServer(facilitatorClient);
|
|
145
|
+
registerExactSvmScheme(server);
|
|
15
146
|
return function withMicropay(handler, routeConfig) {
|
|
16
147
|
const finalConfig = routeConfig || {
|
|
17
148
|
accepts: {
|
package/package.json
CHANGED