@tanakayuto/intmax402-cli 0.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 +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +106 -0
- package/package.json +42 -0
package/README.md
ADDED
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const core_1 = require("@intmax402/core");
|
|
6
|
+
const client_1 = require("@intmax402/client");
|
|
7
|
+
const [, , command, ...args] = process.argv;
|
|
8
|
+
async function main() {
|
|
9
|
+
switch (command) {
|
|
10
|
+
case "test":
|
|
11
|
+
await testCommand(args[0]);
|
|
12
|
+
break;
|
|
13
|
+
case "keygen":
|
|
14
|
+
keygenCommand();
|
|
15
|
+
break;
|
|
16
|
+
case "verify":
|
|
17
|
+
verifyCommand(args[0]);
|
|
18
|
+
break;
|
|
19
|
+
default:
|
|
20
|
+
printUsage();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function testCommand(url) {
|
|
24
|
+
if (!url) {
|
|
25
|
+
console.error("Usage: intmax402 test <url>");
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
console.log(`Testing INTMAX402 flow against ${url}...\n`);
|
|
29
|
+
// Step 1: Initial request
|
|
30
|
+
console.log("Step 1: Sending initial request...");
|
|
31
|
+
const response = await fetch(url);
|
|
32
|
+
console.log(` Status: ${response.status}`);
|
|
33
|
+
if (response.status !== 401 && response.status !== 402) {
|
|
34
|
+
console.log(" No 402 challenge received. Endpoint may not be protected.");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const wwwAuth = response.headers.get("www-authenticate");
|
|
38
|
+
if (!wwwAuth) {
|
|
39
|
+
console.error(" No WWW-Authenticate header found.");
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
console.log(` WWW-Authenticate: ${wwwAuth}`);
|
|
43
|
+
const challenge = (0, core_1.parseWWWAuthenticate)(wwwAuth);
|
|
44
|
+
if (!challenge) {
|
|
45
|
+
console.error(" Failed to parse challenge.");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
console.log(` Mode: ${challenge.mode}`);
|
|
49
|
+
console.log(` Nonce: ${challenge.nonce}`);
|
|
50
|
+
// Step 2: Generate key and sign
|
|
51
|
+
console.log("\nStep 2: Generating key and signing...");
|
|
52
|
+
const privateKey = "0x" + (0, crypto_1.randomBytes)(32).toString("hex");
|
|
53
|
+
const client = new client_1.INTMAX402Client({ privateKey });
|
|
54
|
+
await client.init();
|
|
55
|
+
console.log(` Address: ${client.getAddress()}`);
|
|
56
|
+
const signature = await client.sign(challenge.nonce);
|
|
57
|
+
console.log(` Signature: ${signature.slice(0, 20)}...`);
|
|
58
|
+
// Step 3: Retry with credentials
|
|
59
|
+
console.log("\nStep 3: Retrying with credentials...");
|
|
60
|
+
const retryResponse = await client.fetch(url);
|
|
61
|
+
console.log(` Status: ${retryResponse.status}`);
|
|
62
|
+
if (retryResponse.ok) {
|
|
63
|
+
const body = await retryResponse.text();
|
|
64
|
+
console.log(` Response: ${body.slice(0, 200)}`);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.log(` Response: ${await retryResponse.text()}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function keygenCommand() {
|
|
71
|
+
const privateKey = "0x" + (0, crypto_1.randomBytes)(32).toString("hex");
|
|
72
|
+
const client = new client_1.INTMAX402Client({ privateKey });
|
|
73
|
+
console.log("Generated test keypair:");
|
|
74
|
+
console.log(` Private Key: ${privateKey}`);
|
|
75
|
+
console.log(` Address: ${client.getAddress()}`);
|
|
76
|
+
}
|
|
77
|
+
function verifyCommand(header) {
|
|
78
|
+
if (!header) {
|
|
79
|
+
console.error("Usage: intmax402 verify <authorization-header>");
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
const credential = (0, core_1.parseAuthorization)(header);
|
|
83
|
+
if (!credential) {
|
|
84
|
+
console.error("Failed to parse Authorization header.");
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
console.log("Parsed credential:");
|
|
88
|
+
console.log(` Address: ${credential.address}`);
|
|
89
|
+
console.log(` Nonce: ${credential.nonce}`);
|
|
90
|
+
console.log(` Signature: ${credential.signature.slice(0, 20)}...`);
|
|
91
|
+
if (credential.txHash) {
|
|
92
|
+
console.log(` TX Hash: ${credential.txHash}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function printUsage() {
|
|
96
|
+
console.log("intmax402 CLI - HTTP 402 Payment Gate Test Tool");
|
|
97
|
+
console.log("");
|
|
98
|
+
console.log("Usage:");
|
|
99
|
+
console.log(" intmax402 test <url> Test 402 flow against a URL");
|
|
100
|
+
console.log(" intmax402 keygen Generate a test ETH keypair");
|
|
101
|
+
console.log(" intmax402 verify <header> Parse an Authorization header");
|
|
102
|
+
}
|
|
103
|
+
main().catch((err) => {
|
|
104
|
+
console.error("Error:", err.message);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tanakayuto/intmax402-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"bin": {
|
|
6
|
+
"intmax402": "dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@tanakayuto/intmax402-core": "0.1.0",
|
|
10
|
+
"@tanakayuto/intmax402-client": "0.1.0"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"typescript": "^5.4.0",
|
|
14
|
+
"@types/node": "^20.0.0"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/zaq2989/intmax402"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"intmax",
|
|
30
|
+
"http-402",
|
|
31
|
+
"payment",
|
|
32
|
+
"ai-agent",
|
|
33
|
+
"express",
|
|
34
|
+
"web3",
|
|
35
|
+
"zk"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsc",
|
|
39
|
+
"clean": "rm -rf dist",
|
|
40
|
+
"typecheck": "tsc --noEmit"
|
|
41
|
+
}
|
|
42
|
+
}
|