aipp-node 1.1.0 → 1.2.1

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.
@@ -0,0 +1,29 @@
1
+ import { AippConfig, ChargeParams, ChargeResponse, ChargeStatus, ReceiptResponse, MarketplaceManifest } from './types';
2
+ export declare class Aipp {
3
+ private apiKey;
4
+ private baseUrl;
5
+ constructor(config: AippConfig);
6
+ private request;
7
+ /**
8
+ * Creates a new Invoice (either L402 or x402)
9
+ */
10
+ createCharge(params: ChargeParams): Promise<ChargeResponse>;
11
+ /**
12
+ * Checks the status of an existing charge
13
+ */
14
+ getCharge(paymentHash: string, txHash?: string): Promise<ChargeStatus>;
15
+ /**
16
+ * Triggers a manual withdrawal of your merchant balance
17
+ */
18
+ payout(): Promise<import('./types').PayoutResponse>;
19
+ /**
20
+ * Retrieves an EU AI Act Article 26 compliant receipt for a settled invoice.
21
+ * Only available for invoices with status = 'settled'.
22
+ */
23
+ getReceipt(paymentHash: string): Promise<ReceiptResponse>;
24
+ /**
25
+ * Returns the PaidMCP.dev compatible marketplace manifest for this merchant.
26
+ * Use this JSON to list your AIPP-protected endpoints on AI agent directories.
27
+ */
28
+ getMarketplaceManifest(): Promise<MarketplaceManifest>;
29
+ }
package/dist/client.js ADDED
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Aipp = void 0;
4
+ class Aipp {
5
+ constructor(config) {
6
+ if (!config.apiKey) {
7
+ throw new Error('AIPP: apiKey is required');
8
+ }
9
+ this.apiKey = config.apiKey;
10
+ this.baseUrl = config.baseUrl || 'https://aipp.dev';
11
+ }
12
+ async request(endpoint, options = {}) {
13
+ const url = `${this.baseUrl}${endpoint}`;
14
+ const headers = {
15
+ 'Content-Type': 'application/json',
16
+ 'X-Api-Key': this.apiKey,
17
+ ...options.headers,
18
+ };
19
+ const response = await fetch(url, { ...options, headers });
20
+ if (!response.ok) {
21
+ let errorData;
22
+ try {
23
+ errorData = await response.json();
24
+ }
25
+ catch (err) {
26
+ throw new Error(`AIPP API Error: ${response.status} ${response.statusText}`);
27
+ }
28
+ throw new Error(`AIPP API Error: ${errorData.error || response.statusText}`);
29
+ }
30
+ return response.json();
31
+ }
32
+ /**
33
+ * Creates a new Invoice (either L402 or x402)
34
+ */
35
+ async createCharge(params) {
36
+ if (!params.amountSats && !params.amountUsd) {
37
+ throw new Error('AIPP: Either amountSats or amountUsd is required');
38
+ }
39
+ const body = { memo: params.memo };
40
+ if (params.amountSats)
41
+ body.amount_sats = params.amountSats;
42
+ if (params.amountUsd)
43
+ body.amount_usd = params.amountUsd;
44
+ if (params.protocol)
45
+ body.protocol = params.protocol;
46
+ return this.request('/invoice/create', {
47
+ method: 'POST',
48
+ body: JSON.stringify(body),
49
+ });
50
+ }
51
+ /**
52
+ * Checks the status of an existing charge
53
+ */
54
+ async getCharge(paymentHash, txHash) {
55
+ if (!paymentHash) {
56
+ throw new Error('AIPP: paymentHash is required');
57
+ }
58
+ const query = txHash ? `?tx_hash=${txHash}` : '';
59
+ return this.request(`/invoice/status/${paymentHash}${query}`, {
60
+ method: 'GET',
61
+ });
62
+ }
63
+ /**
64
+ * Triggers a manual withdrawal of your merchant balance
65
+ */
66
+ async payout() {
67
+ return this.request('/merchant/payout', {
68
+ method: 'POST',
69
+ });
70
+ }
71
+ /**
72
+ * Retrieves an EU AI Act Article 26 compliant receipt for a settled invoice.
73
+ * Only available for invoices with status = 'settled'.
74
+ */
75
+ async getReceipt(paymentHash) {
76
+ if (!paymentHash) {
77
+ throw new Error('AIPP: paymentHash is required');
78
+ }
79
+ return this.request(`/invoice/receipt/${paymentHash}`, {
80
+ method: 'GET',
81
+ });
82
+ }
83
+ /**
84
+ * Returns the PaidMCP.dev compatible marketplace manifest for this merchant.
85
+ * Use this JSON to list your AIPP-protected endpoints on AI agent directories.
86
+ */
87
+ async getMarketplaceManifest() {
88
+ return this.request('/paidmcp.json', {
89
+ method: 'GET',
90
+ });
91
+ }
92
+ }
93
+ exports.Aipp = Aipp;
package/dist/index.d.ts CHANGED
@@ -1,58 +1,3 @@
1
- interface AippConfig {
2
- apiKey: string;
3
- baseUrl?: string;
4
- }
5
- interface ChargeParams {
6
- amountSats?: number;
7
- amountUsd?: number;
8
- memo?: string;
9
- }
10
- interface ChargeResponse {
11
- payment_request: string;
12
- payment_hash: string;
13
- amount_sats: number;
14
- }
15
- interface ChargeStatus {
16
- status: 'pending' | 'settled';
17
- payment_hash: string;
18
- amount_sats: number;
19
- }
20
- interface AippErrorResponse {
21
- error: string;
22
- code?: string;
23
- }
24
- interface PayoutResponse {
25
- message: string;
26
- amount_sats?: number;
27
- }
28
-
29
- declare class Aipp {
30
- private apiKey;
31
- private baseUrl;
32
- constructor(config: AippConfig);
33
- private request;
34
- /**
35
- * Creates a new Lightning Invoice
36
- */
37
- createCharge(params: ChargeParams): Promise<ChargeResponse>;
38
- /**
39
- * Checks the status of an existing charge
40
- */
41
- getCharge(paymentHash: string): Promise<ChargeStatus>;
42
- /**
43
- * Triggers a manual withdrawal of your merchant balance
44
- */
45
- payout(): Promise<PayoutResponse>;
46
- }
47
-
48
- interface L402Options {
49
- client: Aipp;
50
- jwtSecret: string;
51
- resourceId: string;
52
- amountSats?: number;
53
- amountUsd?: number;
54
- expiresInSeconds?: number;
55
- }
56
- declare function l402Paywall(options: L402Options): (req: any, res: any, next: any) => Promise<any>;
57
-
58
- export { Aipp, type AippConfig, type AippErrorResponse, type ChargeParams, type ChargeResponse, type ChargeStatus, type L402Options, type PayoutResponse, l402Paywall };
1
+ export * from './client';
2
+ export * from './types';
3
+ export * from './middleware';
package/dist/index.js CHANGED
@@ -1,203 +1,19 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- Aipp: () => Aipp,
34
- l402Paywall: () => l402Paywall
35
- });
36
- module.exports = __toCommonJS(index_exports);
37
-
38
- // src/client.ts
39
- var Aipp = class {
40
- apiKey;
41
- baseUrl;
42
- constructor(config) {
43
- if (!config.apiKey) {
44
- throw new Error("AIPP: apiKey is required");
45
- }
46
- this.apiKey = config.apiKey;
47
- this.baseUrl = config.baseUrl || "https://aipp.dev";
48
- }
49
- async request(endpoint, options = {}) {
50
- const url = `${this.baseUrl}${endpoint}`;
51
- const headers = {
52
- "Content-Type": "application/json",
53
- "X-Api-Key": this.apiKey,
54
- ...options.headers
55
- };
56
- const response = await fetch(url, { ...options, headers });
57
- if (!response.ok) {
58
- let errorData;
59
- try {
60
- errorData = await response.json();
61
- } catch (err) {
62
- throw new Error(`AIPP API Error: ${response.status} ${response.statusText}`);
63
- }
64
- throw new Error(`AIPP API Error: ${errorData.error || response.statusText}`);
65
- }
66
- return response.json();
67
- }
68
- /**
69
- * Creates a new Lightning Invoice
70
- */
71
- async createCharge(params) {
72
- if (!params.amountSats && !params.amountUsd) {
73
- throw new Error("AIPP: Either amountSats or amountUsd is required");
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]; } };
74
7
  }
75
- const body = { memo: params.memo };
76
- if (params.amountSats) body.amount_sats = params.amountSats;
77
- if (params.amountUsd) body.amount_usd = params.amountUsd;
78
- return this.request("/invoice/create", {
79
- method: "POST",
80
- body: JSON.stringify(body)
81
- });
82
- }
83
- /**
84
- * Checks the status of an existing charge
85
- */
86
- async getCharge(paymentHash) {
87
- if (!paymentHash) {
88
- throw new Error("AIPP: paymentHash is required");
89
- }
90
- return this.request(`/invoice/status/${paymentHash}`, {
91
- method: "GET"
92
- });
93
- }
94
- /**
95
- * Triggers a manual withdrawal of your merchant balance
96
- */
97
- async payout() {
98
- return this.request("/merchant/payout", {
99
- method: "POST"
100
- });
101
- }
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);
102
15
  };
103
-
104
- // src/middleware.ts
105
- var import_crypto2 = __toESM(require("crypto"));
106
-
107
- // src/jwt.ts
108
- var import_crypto = __toESM(require("crypto"));
109
- function base64urlEncode(str) {
110
- const buf = Buffer.isBuffer(str) ? str : Buffer.from(str);
111
- return buf.toString("base64url");
112
- }
113
- function base64urlDecode(str) {
114
- return Buffer.from(str, "base64url").toString("utf8");
115
- }
116
- function signJwt(payload, secret) {
117
- const header = { alg: "HS256", typ: "JWT" };
118
- const encodedHeader = base64urlEncode(JSON.stringify(header));
119
- const encodedPayload = base64urlEncode(JSON.stringify(payload));
120
- const data = `${encodedHeader}.${encodedPayload}`;
121
- const signature = import_crypto.default.createHmac("sha256", secret).update(data).digest("base64url");
122
- return `${data}.${signature}`;
123
- }
124
- function verifyJwt(token, secret) {
125
- const parts = token.split(".");
126
- if (parts.length !== 3) {
127
- throw new Error("Invalid JWT format");
128
- }
129
- const [encodedHeader, encodedPayload, signature] = parts;
130
- const data = `${encodedHeader}.${encodedPayload}`;
131
- const expectedSignature = import_crypto.default.createHmac("sha256", secret).update(data).digest("base64url");
132
- const signatureBuffer = Buffer.from(signature);
133
- const expectedBuffer = Buffer.from(expectedSignature);
134
- if (signatureBuffer.length !== expectedBuffer.length || !import_crypto.default.timingSafeEqual(signatureBuffer, expectedBuffer)) {
135
- throw new Error("Invalid JWT signature");
136
- }
137
- const payload = JSON.parse(base64urlDecode(encodedPayload));
138
- if (payload.exp && Date.now() >= payload.exp * 1e3) {
139
- throw new Error("JWT expired");
140
- }
141
- return payload;
142
- }
143
-
144
- // src/middleware.ts
145
- function l402Paywall(options) {
146
- if (!options.amountSats && !options.amountUsd) {
147
- throw new Error("Either amountSats or amountUsd must be provided for l402Paywall");
148
- }
149
- return async (req, res, next) => {
150
- const authHeader = req.headers.authorization || req.headers.Authorization;
151
- let valid = false;
152
- if (authHeader && typeof authHeader === "string" && authHeader.startsWith("L402 ")) {
153
- const parts = authHeader.substring(5).split(":");
154
- if (parts.length === 2) {
155
- const [macaroonStr, preimage] = parts;
156
- try {
157
- const payload = verifyJwt(macaroonStr, options.jwtSecret);
158
- if (payload.resource_id !== options.resourceId) {
159
- throw new Error("Invalid resource");
160
- }
161
- const preimageHash = import_crypto2.default.createHash("sha256").update(Buffer.from(preimage, "hex")).digest("hex");
162
- const expectedHash = payload.payment_hash;
163
- if (typeof expectedHash === "string" && expectedHash.length === preimageHash.length && import_crypto2.default.timingSafeEqual(Buffer.from(preimageHash, "hex"), Buffer.from(expectedHash, "hex"))) {
164
- valid = true;
165
- }
166
- } catch (e) {
167
- }
168
- }
169
- }
170
- if (valid) {
171
- return next();
172
- }
173
- try {
174
- const charge = await options.client.createCharge({
175
- amountSats: options.amountSats,
176
- amountUsd: options.amountUsd,
177
- memo: `L402 Payment for ${options.resourceId}`
178
- });
179
- const expiresIn = options.expiresInSeconds || 3600;
180
- const payload = {
181
- payment_hash: charge.payment_hash,
182
- resource_id: options.resourceId,
183
- exp: Math.floor(Date.now() / 1e3) + expiresIn
184
- };
185
- const jwtToken = signJwt(payload, options.jwtSecret);
186
- res.status(402);
187
- res.setHeader("Www-Authenticate", `L402 macaroon="${jwtToken}" invoice="${charge.payment_request}"`);
188
- res.json({
189
- error: "Payment Required",
190
- code: "L402",
191
- payment_request: charge.payment_request,
192
- macaroon: jwtToken
193
- });
194
- } catch (err) {
195
- res.status(500).json({ error: "Failed to generate L402 challenge", details: err.message || err });
196
- }
197
- };
198
- }
199
- // Annotate the CommonJS export names for ESM import in node:
200
- 0 && (module.exports = {
201
- Aipp,
202
- l402Paywall
203
- });
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./client"), exports);
18
+ __exportStar(require("./types"), exports);
19
+ __exportStar(require("./middleware"), exports);
package/dist/jwt.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function signJwt(payload: any, secret: string): string;
2
+ export declare function verifyJwt(token: string, secret: string): any;
package/dist/jwt.js ADDED
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.signJwt = signJwt;
7
+ exports.verifyJwt = verifyJwt;
8
+ const crypto_1 = __importDefault(require("crypto"));
9
+ function base64urlEncode(str) {
10
+ const buf = Buffer.isBuffer(str) ? str : Buffer.from(str);
11
+ return buf.toString('base64url');
12
+ }
13
+ function base64urlDecode(str) {
14
+ return Buffer.from(str, 'base64url').toString('utf8');
15
+ }
16
+ function signJwt(payload, secret) {
17
+ const header = { alg: 'HS256', typ: 'JWT' };
18
+ const encodedHeader = base64urlEncode(JSON.stringify(header));
19
+ const encodedPayload = base64urlEncode(JSON.stringify(payload));
20
+ const data = `${encodedHeader}.${encodedPayload}`;
21
+ const signature = crypto_1.default.createHmac('sha256', secret).update(data).digest('base64url');
22
+ return `${data}.${signature}`;
23
+ }
24
+ function verifyJwt(token, secret) {
25
+ const parts = token.split('.');
26
+ if (parts.length !== 3) {
27
+ throw new Error('Invalid JWT format');
28
+ }
29
+ const [encodedHeader, encodedPayload, signature] = parts;
30
+ const data = `${encodedHeader}.${encodedPayload}`;
31
+ const expectedSignature = crypto_1.default.createHmac('sha256', secret).update(data).digest('base64url');
32
+ // Constant time comparison to prevent timing attacks
33
+ const signatureBuffer = Buffer.from(signature);
34
+ const expectedBuffer = Buffer.from(expectedSignature);
35
+ if (signatureBuffer.length !== expectedBuffer.length || !crypto_1.default.timingSafeEqual(signatureBuffer, expectedBuffer)) {
36
+ throw new Error('Invalid JWT signature');
37
+ }
38
+ const payload = JSON.parse(base64urlDecode(encodedPayload));
39
+ if (payload.exp && Date.now() >= payload.exp * 1000) {
40
+ throw new Error('JWT expired');
41
+ }
42
+ return payload;
43
+ }
@@ -0,0 +1,16 @@
1
+ import { Aipp } from './client';
2
+ export interface L402Options {
3
+ client: Aipp;
4
+ jwtSecret: string;
5
+ resourceId: string;
6
+ amountSats?: number;
7
+ amountUsd?: number;
8
+ expiresInSeconds?: number;
9
+ }
10
+ export declare function l402Paywall(options: L402Options): (req: any, res: any, next: any) => Promise<any>;
11
+ export interface X402Options {
12
+ client: Aipp;
13
+ resourceId: string;
14
+ amountUsd: number;
15
+ }
16
+ export declare function x402Paywall(options: X402Options): (req: any, res: any, next: any) => Promise<any>;
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.l402Paywall = l402Paywall;
7
+ exports.x402Paywall = x402Paywall;
8
+ const crypto_1 = __importDefault(require("crypto"));
9
+ const jwt_1 = require("./jwt");
10
+ function l402Paywall(options) {
11
+ if (!options.amountSats && !options.amountUsd) {
12
+ throw new Error('Either amountSats or amountUsd must be provided for l402Paywall');
13
+ }
14
+ return async (req, res, next) => {
15
+ const authHeader = req.headers.authorization || req.headers.Authorization;
16
+ let valid = false;
17
+ if (authHeader && typeof authHeader === 'string' && authHeader.startsWith('L402 ')) {
18
+ const parts = authHeader.substring(5).split(':');
19
+ if (parts.length === 2) {
20
+ const [macaroonStr, preimage] = parts;
21
+ try {
22
+ // Verify JWT signature and expiration
23
+ const payload = (0, jwt_1.verifyJwt)(macaroonStr, options.jwtSecret);
24
+ if (payload.resource_id !== options.resourceId) {
25
+ throw new Error('Invalid resource');
26
+ }
27
+ // Verify preimage hash matches payment_hash securely
28
+ const preimageHash = crypto_1.default.createHash('sha256').update(Buffer.from(preimage, 'hex')).digest('hex');
29
+ const expectedHash = payload.payment_hash;
30
+ if (typeof expectedHash === 'string' &&
31
+ expectedHash.length === preimageHash.length &&
32
+ crypto_1.default.timingSafeEqual(Buffer.from(preimageHash, 'hex'), Buffer.from(expectedHash, 'hex'))) {
33
+ valid = true;
34
+ }
35
+ }
36
+ catch (e) {
37
+ // Invalid or expired JWT -> Fall through to 402 and issue new invoice
38
+ }
39
+ }
40
+ }
41
+ if (valid) {
42
+ return next();
43
+ }
44
+ try {
45
+ // Create invoice via AIPP
46
+ const charge = await options.client.createCharge({
47
+ amountSats: options.amountSats,
48
+ amountUsd: options.amountUsd,
49
+ memo: `L402 Payment for ${options.resourceId}`
50
+ });
51
+ // Issue JWT
52
+ const expiresIn = options.expiresInSeconds || 3600; // default 1 hour
53
+ const payload = {
54
+ payment_hash: charge.payment_hash,
55
+ resource_id: options.resourceId,
56
+ exp: Math.floor(Date.now() / 1000) + expiresIn
57
+ };
58
+ const jwtToken = (0, jwt_1.signJwt)(payload, options.jwtSecret);
59
+ res.status(402);
60
+ res.setHeader('Www-Authenticate', `L402 macaroon="${jwtToken}" invoice="${charge.payment_request}"`);
61
+ res.json({
62
+ error: "Payment Required",
63
+ code: "L402",
64
+ payment_request: charge.payment_request,
65
+ macaroon: jwtToken
66
+ });
67
+ }
68
+ catch (err) {
69
+ res.status(500).json({ error: "Failed to generate L402 challenge", details: err.message || err });
70
+ }
71
+ };
72
+ }
73
+ function x402Paywall(options) {
74
+ return async (req, res, next) => {
75
+ const authHeader = req.headers.authorization || req.headers.Authorization;
76
+ let txHash = (req.query.tx_hash || req.headers['payment-signature'] || req.headers['x-payment-signature']);
77
+ let paymentHash = (req.query.payment_hash || req.headers['x-payment-hash']);
78
+ if (!txHash && authHeader && typeof authHeader === 'string') {
79
+ if (authHeader.startsWith('Bearer ')) {
80
+ txHash = authHeader.substring(7).trim();
81
+ }
82
+ else if (authHeader.startsWith('x402 ')) {
83
+ txHash = authHeader.substring(5).trim();
84
+ }
85
+ else if (authHeader.startsWith('L402 ')) {
86
+ // Fallback or double format check
87
+ const parts = authHeader.substring(5).split(':');
88
+ if (parts.length === 2) {
89
+ paymentHash = parts[0];
90
+ txHash = parts[1];
91
+ }
92
+ }
93
+ }
94
+ if (paymentHash && txHash) {
95
+ try {
96
+ const chargeStatus = await options.client.getCharge(paymentHash, txHash);
97
+ if (chargeStatus.status === 'settled') {
98
+ return next();
99
+ }
100
+ }
101
+ catch (e) {
102
+ // Validation failed, proceed to challenge
103
+ }
104
+ }
105
+ try {
106
+ const charge = await options.client.createCharge({
107
+ amountUsd: options.amountUsd,
108
+ protocol: 'x402',
109
+ memo: `x402 Payment for ${options.resourceId}`
110
+ });
111
+ const challengeObj = {
112
+ scheme: 'exact',
113
+ network: 'base',
114
+ payTo: charge.pay_to || '',
115
+ price: options.amountUsd.toFixed(2),
116
+ token: charge.token || '',
117
+ payment_hash: charge.payment_hash
118
+ };
119
+ const challengeBase64 = Buffer.from(JSON.stringify(challengeObj), 'utf8').toString('base64');
120
+ res.setHeader('PAYMENT-REQUIRED', challengeBase64);
121
+ res.status(402);
122
+ res.json({
123
+ error: "Payment Required",
124
+ code: "x402",
125
+ payment_hash: charge.payment_hash,
126
+ pay_to: challengeObj.payTo,
127
+ price: challengeObj.price,
128
+ token: challengeObj.token,
129
+ network: challengeObj.network
130
+ });
131
+ }
132
+ catch (err) {
133
+ res.status(500).json({ error: "Failed to generate x402 challenge", details: err.message || err });
134
+ }
135
+ };
136
+ }
@@ -0,0 +1,75 @@
1
+ export interface AippConfig {
2
+ apiKey: string;
3
+ baseUrl?: string;
4
+ }
5
+ export interface ChargeParams {
6
+ amountSats?: number;
7
+ amountUsd?: number;
8
+ memo?: string;
9
+ protocol?: 'L402' | 'x402';
10
+ }
11
+ export interface ChargeResponse {
12
+ payment_hash: string;
13
+ protocol: 'L402' | 'x402';
14
+ amount_usd?: number;
15
+ pay_to?: string;
16
+ network?: string;
17
+ token?: string;
18
+ payment_request?: string;
19
+ amount_sats?: number;
20
+ }
21
+ export interface ChargeStatus {
22
+ paid: boolean;
23
+ status: 'pending' | 'settled';
24
+ preimage: string | null;
25
+ }
26
+ export interface AippErrorResponse {
27
+ error: string;
28
+ code?: string;
29
+ }
30
+ export interface PayoutResponse {
31
+ message: string;
32
+ amount_sats?: number;
33
+ amount_usd?: number;
34
+ }
35
+ export interface ReceiptCompliance {
36
+ regulation: string;
37
+ note: string;
38
+ }
39
+ export interface ReceiptFinancials {
40
+ currency: string;
41
+ total_amount: number;
42
+ merchant_amount: number;
43
+ platform_fee: number;
44
+ }
45
+ export interface ReceiptPaymentDetails {
46
+ protocol: string;
47
+ proof: string | null;
48
+ merchant_destination: string | null;
49
+ }
50
+ /** EU AI Act Article 26 compliant receipt for a settled invoice */
51
+ export interface ReceiptResponse {
52
+ receipt_id: string;
53
+ transaction_id: string;
54
+ date: string;
55
+ status: string;
56
+ compliance: ReceiptCompliance;
57
+ payment_details: ReceiptPaymentDetails;
58
+ financials: ReceiptFinancials;
59
+ }
60
+ export interface MarketplaceTool {
61
+ name: string;
62
+ description: string;
63
+ priceUsdt: number;
64
+ }
65
+ /** PaidMCP.dev compatible manifest for listing on AI agent marketplaces */
66
+ export interface MarketplaceManifest {
67
+ id: string;
68
+ name: string;
69
+ tagline: string;
70
+ description: string;
71
+ endpoint: string;
72
+ chains: string[];
73
+ tools: MarketplaceTool[];
74
+ tags: string[];
75
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });