@tanakayuto/intmax402-core 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 ADDED
@@ -0,0 +1,5 @@
1
+ # @intmax402/core
2
+
3
+ Part of [intmax402](https://github.com/zaq2989/intmax402) — HTTP 402, reimagined for AI agents.
4
+
5
+ See [main README](https://github.com/zaq2989/intmax402) for full documentation.
@@ -0,0 +1,4 @@
1
+ export * from "./types";
2
+ export { generateNonce } from "./nonce";
3
+ export { verifyNonce } from "./verify";
4
+ export { parseWWWAuthenticate, parseAuthorization } from "./parse";
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.parseAuthorization = exports.parseWWWAuthenticate = exports.verifyNonce = exports.generateNonce = void 0;
18
+ __exportStar(require("./types"), exports);
19
+ var nonce_1 = require("./nonce");
20
+ Object.defineProperty(exports, "generateNonce", { enumerable: true, get: function () { return nonce_1.generateNonce; } });
21
+ var verify_1 = require("./verify");
22
+ Object.defineProperty(exports, "verifyNonce", { enumerable: true, get: function () { return verify_1.verifyNonce; } });
23
+ var parse_1 = require("./parse");
24
+ Object.defineProperty(exports, "parseWWWAuthenticate", { enumerable: true, get: function () { return parse_1.parseWWWAuthenticate; } });
25
+ Object.defineProperty(exports, "parseAuthorization", { enumerable: true, get: function () { return parse_1.parseAuthorization; } });
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generate a stateless nonce.
3
+ * Time-windowed + path-bound. IP binding is optional (disabled by default for agent compatibility).
4
+ */
5
+ export declare function generateNonce(secret: string, ip: string, path: string, bindIp?: boolean): string;
6
+ /**
7
+ * Verify a nonce. Checks current and previous window for clock skew tolerance.
8
+ */
9
+ export declare function verifyNonce(nonce: string, secret: string, ip: string, path: string, bindIp?: boolean): boolean;
package/dist/nonce.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateNonce = generateNonce;
4
+ exports.verifyNonce = verifyNonce;
5
+ const crypto_1 = require("crypto");
6
+ const WINDOW_MS = 30_000; // 30 second windows
7
+ function getTimeWindow() {
8
+ return Math.floor(Date.now() / WINDOW_MS);
9
+ }
10
+ /**
11
+ * Generate a stateless nonce.
12
+ * Time-windowed + path-bound. IP binding is optional (disabled by default for agent compatibility).
13
+ */
14
+ function generateNonce(secret, ip, path, bindIp = false // ← false = AIエージェント対応(IP変動OK)
15
+ ) {
16
+ const window = getTimeWindow();
17
+ const data = bindIp
18
+ ? `${window}:${ip}:${path}`
19
+ : `${window}:${path}`;
20
+ return (0, crypto_1.createHmac)("sha256", secret).update(data).digest("hex");
21
+ }
22
+ /**
23
+ * Verify a nonce. Checks current and previous window for clock skew tolerance.
24
+ */
25
+ function verifyNonce(nonce, secret, ip, path, bindIp = false) {
26
+ const window = getTimeWindow();
27
+ // Check current and previous window (allows up to ~60s of clock skew)
28
+ for (const w of [window, window - 1]) {
29
+ const data = bindIp
30
+ ? `${w}:${ip}:${path}`
31
+ : `${w}:${path}`;
32
+ const expected = (0, crypto_1.createHmac)("sha256", secret).update(data).digest("hex");
33
+ if (expected === nonce)
34
+ return true;
35
+ }
36
+ return false;
37
+ }
@@ -0,0 +1,3 @@
1
+ import { INTMAX402Challenge, INTMAX402Credential } from "./types";
2
+ export declare function parseWWWAuthenticate(header: string): INTMAX402Challenge | null;
3
+ export declare function parseAuthorization(header: string): INTMAX402Credential | null;
package/dist/parse.js ADDED
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseWWWAuthenticate = parseWWWAuthenticate;
4
+ exports.parseAuthorization = parseAuthorization;
5
+ function parseWWWAuthenticate(header) {
6
+ if (!header.startsWith("INTMAX402 "))
7
+ return null;
8
+ const params = header.slice("INTMAX402 ".length);
9
+ const result = {};
10
+ const regex = /(\w+)="([^"]*)"/g;
11
+ let match;
12
+ while ((match = regex.exec(params)) !== null) {
13
+ result[match[1]] = match[2];
14
+ }
15
+ if (!result.realm || !result.nonce || !result.mode)
16
+ return null;
17
+ return {
18
+ realm: result.realm,
19
+ nonce: result.nonce,
20
+ mode: result.mode,
21
+ serverAddress: result.serverAddress,
22
+ amount: result.amount,
23
+ tokenAddress: result.tokenAddress,
24
+ chainId: result.chainId,
25
+ };
26
+ }
27
+ function parseAuthorization(header) {
28
+ if (!header.startsWith("INTMAX402 "))
29
+ return null;
30
+ const params = header.slice("INTMAX402 ".length);
31
+ const result = {};
32
+ const regex = /(\w+)="([^"]*)"/g;
33
+ let match;
34
+ while ((match = regex.exec(params)) !== null) {
35
+ result[match[1]] = match[2];
36
+ }
37
+ if (!result.address || !result.nonce || !result.signature)
38
+ return null;
39
+ return {
40
+ address: result.address,
41
+ nonce: result.nonce,
42
+ signature: result.signature,
43
+ txHash: result.txHash,
44
+ };
45
+ }
@@ -0,0 +1,29 @@
1
+ export type INTMAX402Mode = "identity" | "payment";
2
+ export interface INTMAX402Challenge {
3
+ realm: string;
4
+ nonce: string;
5
+ mode: INTMAX402Mode;
6
+ serverAddress?: string;
7
+ amount?: string;
8
+ tokenAddress?: string;
9
+ chainId?: string;
10
+ }
11
+ export interface INTMAX402Credential {
12
+ address: string;
13
+ nonce: string;
14
+ signature: string;
15
+ txHash?: string;
16
+ }
17
+ export interface INTMAX402Config {
18
+ mode: INTMAX402Mode;
19
+ secret: string;
20
+ serverAddress?: string;
21
+ amount?: string;
22
+ tokenAddress?: string;
23
+ chainId?: string;
24
+ environment?: "mainnet" | "testnet";
25
+ allowList?: string[];
26
+ pricing?: Record<string, string>;
27
+ /** Bind nonce to client IP. Default false (recommended for AI agents). */
28
+ bindIp?: boolean;
29
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export { verifyNonce } from "./nonce";
package/dist/verify.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifyNonce = void 0;
4
+ // Re-export verifyNonce from nonce.ts for backward compatibility
5
+ var nonce_1 = require("./nonce");
6
+ Object.defineProperty(exports, "verifyNonce", { enumerable: true, get: function () { return nonce_1.verifyNonce; } });
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@tanakayuto/intmax402-core",
3
+ "version": "0.1.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "dependencies": {},
7
+ "devDependencies": {
8
+ "typescript": "^5.4.0",
9
+ "@types/node": "^20.0.0"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md"
14
+ ],
15
+ "license": "MIT",
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/zaq2989/intmax402"
22
+ },
23
+ "keywords": [
24
+ "intmax",
25
+ "http-402",
26
+ "payment",
27
+ "ai-agent",
28
+ "express",
29
+ "web3",
30
+ "zk"
31
+ ],
32
+ "scripts": {
33
+ "build": "tsc",
34
+ "clean": "rm -rf dist",
35
+ "typecheck": "tsc --noEmit"
36
+ }
37
+ }