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.
- package/dist/client.d.ts +29 -0
- package/dist/client.js +93 -0
- package/dist/index.d.ts +3 -58
- package/dist/index.js +16 -200
- package/dist/jwt.d.ts +2 -0
- package/dist/jwt.js +43 -0
- package/dist/middleware.d.ts +16 -0
- package/dist/middleware.js +136 -0
- package/dist/types.d.ts +75 -0
- package/dist/types.js +2 -0
- package/package.json +32 -32
- package/src/client.ts +101 -76
- package/src/index.ts +3 -3
- package/src/jwt.ts +48 -48
- package/src/middleware.ts +159 -86
- package/src/types.ts +86 -32
- package/tsconfig.json +14 -14
- package/dist/index.d.mts +0 -58
- package/dist/index.mjs +0 -165
package/src/types.ts
CHANGED
|
@@ -1,32 +1,86 @@
|
|
|
1
|
-
export interface AippConfig {
|
|
2
|
-
apiKey: string;
|
|
3
|
-
baseUrl?: string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export interface ChargeParams {
|
|
7
|
-
amountSats?: number;
|
|
8
|
-
amountUsd?: number;
|
|
9
|
-
memo?: string;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
payment_hash: string;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
amount_sats
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
1
|
+
export interface AippConfig {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
baseUrl?: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface ChargeParams {
|
|
7
|
+
amountSats?: number;
|
|
8
|
+
amountUsd?: number;
|
|
9
|
+
memo?: string;
|
|
10
|
+
protocol?: 'L402' | 'x402';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ChargeResponse {
|
|
14
|
+
payment_hash: string;
|
|
15
|
+
protocol: 'L402' | 'x402';
|
|
16
|
+
amount_usd?: number;
|
|
17
|
+
pay_to?: string;
|
|
18
|
+
network?: string;
|
|
19
|
+
token?: string;
|
|
20
|
+
payment_request?: string; // For L402
|
|
21
|
+
amount_sats?: number; // For L402
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ChargeStatus {
|
|
25
|
+
paid: boolean;
|
|
26
|
+
status: 'pending' | 'settled';
|
|
27
|
+
preimage: string | null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface AippErrorResponse {
|
|
31
|
+
error: string;
|
|
32
|
+
code?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface PayoutResponse {
|
|
36
|
+
message: string;
|
|
37
|
+
amount_sats?: number;
|
|
38
|
+
amount_usd?: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ReceiptCompliance {
|
|
42
|
+
regulation: string;
|
|
43
|
+
note: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ReceiptFinancials {
|
|
47
|
+
currency: string;
|
|
48
|
+
total_amount: number;
|
|
49
|
+
merchant_amount: number;
|
|
50
|
+
platform_fee: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ReceiptPaymentDetails {
|
|
54
|
+
protocol: string;
|
|
55
|
+
proof: string | null;
|
|
56
|
+
merchant_destination: string | null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** EU AI Act Article 26 compliant receipt for a settled invoice */
|
|
60
|
+
export interface ReceiptResponse {
|
|
61
|
+
receipt_id: string;
|
|
62
|
+
transaction_id: string;
|
|
63
|
+
date: string;
|
|
64
|
+
status: string;
|
|
65
|
+
compliance: ReceiptCompliance;
|
|
66
|
+
payment_details: ReceiptPaymentDetails;
|
|
67
|
+
financials: ReceiptFinancials;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface MarketplaceTool {
|
|
71
|
+
name: string;
|
|
72
|
+
description: string;
|
|
73
|
+
priceUsdt: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** PaidMCP.dev compatible manifest for listing on AI agent marketplaces */
|
|
77
|
+
export interface MarketplaceManifest {
|
|
78
|
+
id: string;
|
|
79
|
+
name: string;
|
|
80
|
+
tagline: string;
|
|
81
|
+
description: string;
|
|
82
|
+
endpoint: string;
|
|
83
|
+
chains: string[];
|
|
84
|
+
tools: MarketplaceTool[];
|
|
85
|
+
tags: string[];
|
|
86
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es2022",
|
|
4
|
-
"module": "esnext",
|
|
5
|
-
"moduleResolution": "node",
|
|
6
|
-
"strict": true,
|
|
7
|
-
"esModuleInterop": true,
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"forceConsistentCasingInFileNames": true,
|
|
10
|
-
"declaration": true,
|
|
11
|
-
"outDir": "dist"
|
|
12
|
-
},
|
|
13
|
-
"include": ["src"]
|
|
14
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2022",
|
|
4
|
+
"module": "esnext",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"declaration": true,
|
|
11
|
+
"outDir": "dist"
|
|
12
|
+
},
|
|
13
|
+
"include": ["src"]
|
|
14
|
+
}
|
package/dist/index.d.mts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
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 };
|
package/dist/index.mjs
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
// src/client.ts
|
|
2
|
-
var Aipp = class {
|
|
3
|
-
apiKey;
|
|
4
|
-
baseUrl;
|
|
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
|
-
} catch (err) {
|
|
25
|
-
throw new Error(`AIPP API Error: ${response.status} ${response.statusText}`);
|
|
26
|
-
}
|
|
27
|
-
throw new Error(`AIPP API Error: ${errorData.error || response.statusText}`);
|
|
28
|
-
}
|
|
29
|
-
return response.json();
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Creates a new Lightning Invoice
|
|
33
|
-
*/
|
|
34
|
-
async createCharge(params) {
|
|
35
|
-
if (!params.amountSats && !params.amountUsd) {
|
|
36
|
-
throw new Error("AIPP: Either amountSats or amountUsd is required");
|
|
37
|
-
}
|
|
38
|
-
const body = { memo: params.memo };
|
|
39
|
-
if (params.amountSats) body.amount_sats = params.amountSats;
|
|
40
|
-
if (params.amountUsd) body.amount_usd = params.amountUsd;
|
|
41
|
-
return this.request("/invoice/create", {
|
|
42
|
-
method: "POST",
|
|
43
|
-
body: JSON.stringify(body)
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Checks the status of an existing charge
|
|
48
|
-
*/
|
|
49
|
-
async getCharge(paymentHash) {
|
|
50
|
-
if (!paymentHash) {
|
|
51
|
-
throw new Error("AIPP: paymentHash is required");
|
|
52
|
-
}
|
|
53
|
-
return this.request(`/invoice/status/${paymentHash}`, {
|
|
54
|
-
method: "GET"
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Triggers a manual withdrawal of your merchant balance
|
|
59
|
-
*/
|
|
60
|
-
async payout() {
|
|
61
|
-
return this.request("/merchant/payout", {
|
|
62
|
-
method: "POST"
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
// src/middleware.ts
|
|
68
|
-
import crypto2 from "crypto";
|
|
69
|
-
|
|
70
|
-
// src/jwt.ts
|
|
71
|
-
import crypto from "crypto";
|
|
72
|
-
function base64urlEncode(str) {
|
|
73
|
-
const buf = Buffer.isBuffer(str) ? str : Buffer.from(str);
|
|
74
|
-
return buf.toString("base64url");
|
|
75
|
-
}
|
|
76
|
-
function base64urlDecode(str) {
|
|
77
|
-
return Buffer.from(str, "base64url").toString("utf8");
|
|
78
|
-
}
|
|
79
|
-
function signJwt(payload, secret) {
|
|
80
|
-
const header = { alg: "HS256", typ: "JWT" };
|
|
81
|
-
const encodedHeader = base64urlEncode(JSON.stringify(header));
|
|
82
|
-
const encodedPayload = base64urlEncode(JSON.stringify(payload));
|
|
83
|
-
const data = `${encodedHeader}.${encodedPayload}`;
|
|
84
|
-
const signature = crypto.createHmac("sha256", secret).update(data).digest("base64url");
|
|
85
|
-
return `${data}.${signature}`;
|
|
86
|
-
}
|
|
87
|
-
function verifyJwt(token, secret) {
|
|
88
|
-
const parts = token.split(".");
|
|
89
|
-
if (parts.length !== 3) {
|
|
90
|
-
throw new Error("Invalid JWT format");
|
|
91
|
-
}
|
|
92
|
-
const [encodedHeader, encodedPayload, signature] = parts;
|
|
93
|
-
const data = `${encodedHeader}.${encodedPayload}`;
|
|
94
|
-
const expectedSignature = crypto.createHmac("sha256", secret).update(data).digest("base64url");
|
|
95
|
-
const signatureBuffer = Buffer.from(signature);
|
|
96
|
-
const expectedBuffer = Buffer.from(expectedSignature);
|
|
97
|
-
if (signatureBuffer.length !== expectedBuffer.length || !crypto.timingSafeEqual(signatureBuffer, expectedBuffer)) {
|
|
98
|
-
throw new Error("Invalid JWT signature");
|
|
99
|
-
}
|
|
100
|
-
const payload = JSON.parse(base64urlDecode(encodedPayload));
|
|
101
|
-
if (payload.exp && Date.now() >= payload.exp * 1e3) {
|
|
102
|
-
throw new Error("JWT expired");
|
|
103
|
-
}
|
|
104
|
-
return payload;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// src/middleware.ts
|
|
108
|
-
function l402Paywall(options) {
|
|
109
|
-
if (!options.amountSats && !options.amountUsd) {
|
|
110
|
-
throw new Error("Either amountSats or amountUsd must be provided for l402Paywall");
|
|
111
|
-
}
|
|
112
|
-
return async (req, res, next) => {
|
|
113
|
-
const authHeader = req.headers.authorization || req.headers.Authorization;
|
|
114
|
-
let valid = false;
|
|
115
|
-
if (authHeader && typeof authHeader === "string" && authHeader.startsWith("L402 ")) {
|
|
116
|
-
const parts = authHeader.substring(5).split(":");
|
|
117
|
-
if (parts.length === 2) {
|
|
118
|
-
const [macaroonStr, preimage] = parts;
|
|
119
|
-
try {
|
|
120
|
-
const payload = verifyJwt(macaroonStr, options.jwtSecret);
|
|
121
|
-
if (payload.resource_id !== options.resourceId) {
|
|
122
|
-
throw new Error("Invalid resource");
|
|
123
|
-
}
|
|
124
|
-
const preimageHash = crypto2.createHash("sha256").update(Buffer.from(preimage, "hex")).digest("hex");
|
|
125
|
-
const expectedHash = payload.payment_hash;
|
|
126
|
-
if (typeof expectedHash === "string" && expectedHash.length === preimageHash.length && crypto2.timingSafeEqual(Buffer.from(preimageHash, "hex"), Buffer.from(expectedHash, "hex"))) {
|
|
127
|
-
valid = true;
|
|
128
|
-
}
|
|
129
|
-
} catch (e) {
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (valid) {
|
|
134
|
-
return next();
|
|
135
|
-
}
|
|
136
|
-
try {
|
|
137
|
-
const charge = await options.client.createCharge({
|
|
138
|
-
amountSats: options.amountSats,
|
|
139
|
-
amountUsd: options.amountUsd,
|
|
140
|
-
memo: `L402 Payment for ${options.resourceId}`
|
|
141
|
-
});
|
|
142
|
-
const expiresIn = options.expiresInSeconds || 3600;
|
|
143
|
-
const payload = {
|
|
144
|
-
payment_hash: charge.payment_hash,
|
|
145
|
-
resource_id: options.resourceId,
|
|
146
|
-
exp: Math.floor(Date.now() / 1e3) + expiresIn
|
|
147
|
-
};
|
|
148
|
-
const jwtToken = signJwt(payload, options.jwtSecret);
|
|
149
|
-
res.status(402);
|
|
150
|
-
res.setHeader("Www-Authenticate", `L402 macaroon="${jwtToken}" invoice="${charge.payment_request}"`);
|
|
151
|
-
res.json({
|
|
152
|
-
error: "Payment Required",
|
|
153
|
-
code: "L402",
|
|
154
|
-
payment_request: charge.payment_request,
|
|
155
|
-
macaroon: jwtToken
|
|
156
|
-
});
|
|
157
|
-
} catch (err) {
|
|
158
|
-
res.status(500).json({ error: "Failed to generate L402 challenge", details: err.message || err });
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
export {
|
|
163
|
-
Aipp,
|
|
164
|
-
l402Paywall
|
|
165
|
-
};
|