wolverine-ai 5.4.0 → 5.4.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/bin/wolverine.js +4 -1
- package/package.json +1 -1
- package/src/core/init-server.js +35 -1
- package/src/middleware/x402-fastify.js +14 -35
package/bin/wolverine.js
CHANGED
|
@@ -246,9 +246,12 @@ if (args.includes("--backups")) {
|
|
|
246
246
|
const scriptPath = args.find(a => !a.startsWith("--")) || "server/index.js";
|
|
247
247
|
|
|
248
248
|
// Initialize server/ from template if it doesn't exist (first run)
|
|
249
|
-
const { initServer } = require("../src/core/init-server");
|
|
249
|
+
const { initServer, ensureX402Deps } = require("../src/core/init-server");
|
|
250
250
|
initServer(process.cwd(), scriptPath);
|
|
251
251
|
|
|
252
|
+
// Ensure x402 payment deps are installed (if vault exists)
|
|
253
|
+
ensureX402Deps(process.cwd());
|
|
254
|
+
|
|
252
255
|
// System detection (for analytics + dashboard, NOT for forking)
|
|
253
256
|
// Wolverine runs as a single process manager. If users want clustering,
|
|
254
257
|
// they handle it inside their server (e.g. @fastify/cluster, pm2 cluster mode).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wolverine-ai",
|
|
3
|
-
"version": "5.4.
|
|
3
|
+
"version": "5.4.2",
|
|
4
4
|
"description": "Self-healing Node.js server framework powered by AI. Catches crashes, diagnoses errors, generates fixes, verifies, and restarts — automatically.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
package/src/core/init-server.js
CHANGED
|
@@ -55,4 +55,38 @@ function _copyDir(src, dest) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Ensure x402 payment dependencies are installed.
|
|
60
|
+
* Called on startup — checks if @coinbase/x402 is resolvable.
|
|
61
|
+
* Auto-installs if vault is initialized (user wants x402).
|
|
62
|
+
*/
|
|
63
|
+
function ensureX402Deps(cwd) {
|
|
64
|
+
// Check if x402 packages are needed
|
|
65
|
+
const vaultPath = path.join(cwd, ".wolverine", "vault", "eth.vault");
|
|
66
|
+
const hasVault = fs.existsSync(vaultPath);
|
|
67
|
+
if (!hasVault) return; // No vault = no x402 needed
|
|
68
|
+
|
|
69
|
+
// Check if already installed
|
|
70
|
+
try {
|
|
71
|
+
require.resolve("@coinbase/x402");
|
|
72
|
+
require.resolve("x402");
|
|
73
|
+
return; // Already installed
|
|
74
|
+
} catch {}
|
|
75
|
+
|
|
76
|
+
// Auto-install x402 deps
|
|
77
|
+
console.log(chalk.blue(" 📦 Installing x402 payment dependencies..."));
|
|
78
|
+
try {
|
|
79
|
+
const { execSync } = require("child_process");
|
|
80
|
+
execSync("npm install @coinbase/x402 x402 viem --no-save --ignore-engines 2>/dev/null", {
|
|
81
|
+
cwd,
|
|
82
|
+
stdio: "pipe",
|
|
83
|
+
timeout: 60000,
|
|
84
|
+
});
|
|
85
|
+
console.log(chalk.green(" ✅ x402 dependencies installed"));
|
|
86
|
+
} catch (err) {
|
|
87
|
+
console.log(chalk.yellow(` ⚠️ x402 dep install failed: ${err.message?.slice(0, 80)}`));
|
|
88
|
+
console.log(chalk.gray(" Run manually: npm install @coinbase/x402 x402 viem"));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = { initServer, ensureX402Deps };
|
|
@@ -174,50 +174,29 @@ async function x402Plugin(fastify, opts) {
|
|
|
174
174
|
return;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
//
|
|
177
|
+
// Settle via facilitator BEFORE handler runs — USDC must move before granting access
|
|
178
178
|
const payer = decodedPayment.payload.authorization.from;
|
|
179
|
-
request.x402 = { paid: true, amount: price, from: payer, value: userValue, verified: true };
|
|
180
|
-
|
|
181
|
-
// Log payment
|
|
182
|
-
_logPayment({ route: request.url, method: request.method, amount: price, from: payer, verified: true, timestamp: Date.now() });
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
// Settlement hook — settle AFTER successful handler response
|
|
186
|
-
fastify.addHook("onSend", async (request, reply, payload) => {
|
|
187
|
-
if (!request.x402?.paid || !_facilitatorClient) return payload;
|
|
188
|
-
if (reply.statusCode >= 400) return payload;
|
|
189
|
-
|
|
190
179
|
try {
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
const decodedPayment = { x402Version: raw.x402Version || 1, scheme: raw.scheme || "exact", network: raw.network || _network, payload: raw.payload };
|
|
194
|
-
|
|
195
|
-
const userValue = decodedPayment.payload.authorization.value;
|
|
196
|
-
const { getAddress } = await import("viem");
|
|
197
|
-
const proto = request.headers["x-forwarded-proto"] || "https";
|
|
198
|
-
const host = request.headers["x-forwarded-host"] || request.headers.host || "localhost";
|
|
199
|
-
const requirements = {
|
|
200
|
-
scheme: "exact", network: _network, maxAmountRequired: userValue,
|
|
201
|
-
resource: `${proto}://${host}${request.url}`, description: "", mimeType: "application/json",
|
|
202
|
-
payTo: getAddress(_payTo), maxTimeoutSeconds: 60, asset: getAddress(USDC_ADDRESS), extra: USDC_EIP712,
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
const settleResult = await _facilitatorClient.settle(decodedPayment, requirements);
|
|
206
|
-
if (settleResult.success) {
|
|
207
|
-
request.x402.txHash = settleResult.transaction;
|
|
208
|
-
request.x402.settled = true;
|
|
209
|
-
console.log(` 💰 x402 settled: ${settleResult.transaction || "confirmed"} (${request.x402.amount} from ${request.x402.from?.slice(0, 10)})`);
|
|
210
|
-
// Update payment log
|
|
211
|
-
_logPayment({ route: request.url, method: request.method, amount: request.x402.amount, from: request.x402.from, txHash: settleResult.transaction, verified: true, settled: true, timestamp: Date.now() });
|
|
212
|
-
} else {
|
|
180
|
+
const settleResult = await _facilitatorClient.settle(decodedPayment, actualRequirements);
|
|
181
|
+
if (!settleResult.success) {
|
|
213
182
|
console.log(` ⚠️ x402 settle failed: ${settleResult.errorReason || "unknown"}`);
|
|
183
|
+
reply.code(402).send({ error: "Payment settlement failed", reason: settleResult.errorReason });
|
|
184
|
+
return;
|
|
214
185
|
}
|
|
186
|
+
const txHash = settleResult.transaction || null;
|
|
187
|
+
console.log(` 💰 x402 settled: ${txHash || "confirmed"} (${price} from ${payer?.slice(0, 10)})`);
|
|
188
|
+
|
|
189
|
+
request.x402 = { paid: true, amount: price, from: payer, value: userValue, verified: true, settled: true, txHash };
|
|
190
|
+
_logPayment({ route: request.url, method: request.method, amount: price, from: payer, txHash, verified: true, settled: true, timestamp: Date.now() });
|
|
215
191
|
} catch (err) {
|
|
216
192
|
console.log(` ⚠️ x402 settle error: ${err.message}`);
|
|
193
|
+
reply.code(402).send({ error: "Payment settlement failed: " + err.message });
|
|
194
|
+
return;
|
|
217
195
|
}
|
|
218
|
-
return payload;
|
|
219
196
|
});
|
|
220
197
|
|
|
198
|
+
// No onSend settle needed — settlement happens in preHandler before handler runs
|
|
199
|
+
|
|
221
200
|
// Public info endpoint
|
|
222
201
|
fastify.get("/x402/info", async () => ({
|
|
223
202
|
payTo: _payTo, network: _network, protocol: "x402", x402Version: 1,
|