@tanakayuto/intmax402-client 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/client
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,17 @@
1
+ export interface INTMAX402ClientOptions {
2
+ privateKey: string;
3
+ environment?: "mainnet" | "testnet";
4
+ }
5
+ export declare class INTMAX402Client {
6
+ private privateKey;
7
+ private environment;
8
+ private address;
9
+ private initialized;
10
+ constructor(options: INTMAX402ClientOptions);
11
+ private deriveAddress;
12
+ init(): Promise<void>;
13
+ getAddress(): string;
14
+ getRpcUrl(): string;
15
+ sign(nonce: string): Promise<string>;
16
+ fetch(url: string, options?: RequestInit): Promise<Response>;
17
+ }
package/dist/client.js ADDED
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.INTMAX402Client = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const intmax402_core_1 = require("@tanakayuto/intmax402-core");
6
+ const RPC_URLS = {
7
+ mainnet: "https://api.rpc.intmax.io?network=ethereum",
8
+ testnet: "https://sepolia.gateway.tenderly.co",
9
+ };
10
+ class INTMAX402Client {
11
+ privateKey;
12
+ environment;
13
+ address;
14
+ initialized = false;
15
+ constructor(options) {
16
+ this.privateKey = options.privateKey;
17
+ this.environment = options.environment || "testnet";
18
+ this.address = this.deriveAddress(options.privateKey);
19
+ }
20
+ deriveAddress(privateKey) {
21
+ // Derive a deterministic address from private key using hash
22
+ // In production, use secp256k1 to derive the actual Ethereum address
23
+ const hash = (0, crypto_1.createHash)("sha256").update(privateKey).digest("hex");
24
+ return "0x" + hash.slice(0, 40);
25
+ }
26
+ async init() {
27
+ // In production, this would call IntMaxNodeClient.login()
28
+ // which takes ~7 seconds for initial setup
29
+ this.initialized = true;
30
+ }
31
+ getAddress() {
32
+ return this.address;
33
+ }
34
+ getRpcUrl() {
35
+ return RPC_URLS[this.environment];
36
+ }
37
+ async sign(nonce) {
38
+ // Sign the nonce using the private key
39
+ // In production, use secp256k1 to create an Ethereum personal_sign signature
40
+ // For now, create an HMAC-based signature as placeholder
41
+ const message = `\x19Ethereum Signed Message:\n${nonce.length}${nonce}`;
42
+ const sig = (0, crypto_1.createHmac)("sha256", this.privateKey).update(message).digest("hex");
43
+ // Pad to 65 bytes (130 hex chars) to match Ethereum signature format
44
+ const padded = sig.padEnd(130, "0");
45
+ return "0x" + padded;
46
+ }
47
+ async fetch(url, options) {
48
+ // First request - expect 401/402
49
+ const initialResponse = await globalThis.fetch(url, options);
50
+ if (initialResponse.status !== 401 && initialResponse.status !== 402) {
51
+ return initialResponse;
52
+ }
53
+ const wwwAuth = initialResponse.headers.get("www-authenticate");
54
+ if (!wwwAuth) {
55
+ return initialResponse;
56
+ }
57
+ const challenge = (0, intmax402_core_1.parseWWWAuthenticate)(wwwAuth);
58
+ if (!challenge) {
59
+ return initialResponse;
60
+ }
61
+ // Sign the nonce
62
+ const signature = await this.sign(challenge.nonce);
63
+ // Build authorization header
64
+ let authHeader = `INTMAX402 address="${this.address}", nonce="${challenge.nonce}", signature="${signature}"`;
65
+ // If payment mode, would need to send payment first and include txHash
66
+ // For now, just include the signature
67
+ // Retry with credentials
68
+ const retryOptions = {
69
+ ...options,
70
+ headers: {
71
+ ...(options?.headers || {}),
72
+ Authorization: authHeader,
73
+ },
74
+ };
75
+ return globalThis.fetch(url, retryOptions);
76
+ }
77
+ }
78
+ exports.INTMAX402Client = INTMAX402Client;
@@ -0,0 +1 @@
1
+ export { INTMAX402Client, INTMAX402ClientOptions } from "./client";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.INTMAX402Client = void 0;
4
+ var client_1 = require("./client");
5
+ Object.defineProperty(exports, "INTMAX402Client", { enumerable: true, get: function () { return client_1.INTMAX402Client; } });
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@tanakayuto/intmax402-client",
3
+ "version": "0.1.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "dependencies": {
7
+ "@tanakayuto/intmax402-core": "0.1.0"
8
+ },
9
+ "devDependencies": {
10
+ "typescript": "^5.4.0",
11
+ "@types/node": "^20.0.0"
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "README.md"
16
+ ],
17
+ "license": "MIT",
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/zaq2989/intmax402"
24
+ },
25
+ "keywords": [
26
+ "intmax",
27
+ "http-402",
28
+ "payment",
29
+ "ai-agent",
30
+ "express",
31
+ "web3",
32
+ "zk"
33
+ ],
34
+ "scripts": {
35
+ "build": "tsc",
36
+ "clean": "rm -rf dist",
37
+ "typecheck": "tsc --noEmit"
38
+ }
39
+ }