@puga-labs/x402-mantle-sdk 0.1.0 → 0.2.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/dist/index.cjs +66 -3
- package/dist/index.d.cts +37 -2
- package/dist/index.d.ts +37 -2
- package/dist/index.js +66 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -58,6 +58,59 @@ function usdCentsToAtomic(cents, decimals) {
|
|
|
58
58
|
return BigInt(cents) * base;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// src/server/constants.ts
|
|
62
|
+
var DEFAULT_TELEMETRY_ENDPOINT = void 0;
|
|
63
|
+
|
|
64
|
+
// src/server/telemetry.ts
|
|
65
|
+
function createTelemetryEvent(entry, config) {
|
|
66
|
+
const assetConfig = getDefaultAssetForNetwork(entry.network);
|
|
67
|
+
return {
|
|
68
|
+
event: "payment_verified",
|
|
69
|
+
ts: entry.timestamp,
|
|
70
|
+
projectKey: config.projectKey,
|
|
71
|
+
network: entry.network,
|
|
72
|
+
buyer: entry.from,
|
|
73
|
+
payTo: entry.to,
|
|
74
|
+
amountAtomic: entry.valueAtomic,
|
|
75
|
+
asset: entry.asset,
|
|
76
|
+
decimals: assetConfig.decimals,
|
|
77
|
+
nonce: entry.id,
|
|
78
|
+
route: entry.route ?? "unknown",
|
|
79
|
+
// Facilitator metadata
|
|
80
|
+
facilitatorType: "hosted",
|
|
81
|
+
// SDK always uses hosted mode
|
|
82
|
+
facilitatorUrl: entry.facilitatorUrl,
|
|
83
|
+
// From PaymentLogEntry
|
|
84
|
+
// facilitatorAddress is undefined for SDK (not available)
|
|
85
|
+
// Optional metadata
|
|
86
|
+
txHash: entry.txHash,
|
|
87
|
+
priceUsd: entry.paymentRequirements?.price
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
async function sendTelemetry(event, endpoint) {
|
|
91
|
+
const targetEndpoint = endpoint ?? DEFAULT_TELEMETRY_ENDPOINT;
|
|
92
|
+
if (!targetEndpoint) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const response = await fetch(targetEndpoint, {
|
|
97
|
+
method: "POST",
|
|
98
|
+
headers: {
|
|
99
|
+
"Content-Type": "application/json",
|
|
100
|
+
"Authorization": `Bearer ${event.projectKey}`
|
|
101
|
+
},
|
|
102
|
+
body: JSON.stringify(event)
|
|
103
|
+
});
|
|
104
|
+
if (!response.ok) {
|
|
105
|
+
console.warn(
|
|
106
|
+
`[x402-telemetry] Failed to send event: HTTP ${response.status}`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
} catch (err) {
|
|
110
|
+
console.error("[x402-telemetry] Error sending telemetry:", err);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
61
114
|
// src/server/paymentMiddleware.ts
|
|
62
115
|
function getRouteKey(req) {
|
|
63
116
|
const method = (req.method || "GET").toUpperCase();
|
|
@@ -81,7 +134,7 @@ function decodePaymentHeader(paymentHeaderBase64) {
|
|
|
81
134
|
}
|
|
82
135
|
}
|
|
83
136
|
function createPaymentMiddleware(config) {
|
|
84
|
-
const { facilitatorUrl, receiverAddress, routes, onPaymentSettled } = config;
|
|
137
|
+
const { facilitatorUrl, receiverAddress, routes, onPaymentSettled, telemetry } = config;
|
|
85
138
|
if (!facilitatorUrl) {
|
|
86
139
|
throw new Error("facilitatorUrl is required");
|
|
87
140
|
}
|
|
@@ -171,9 +224,17 @@ function createPaymentMiddleware(config) {
|
|
|
171
224
|
asset: assetConfig.address,
|
|
172
225
|
route: routeKey,
|
|
173
226
|
timestamp: Date.now(),
|
|
227
|
+
facilitatorUrl,
|
|
228
|
+
// Pass from config closure
|
|
174
229
|
paymentRequirements
|
|
175
230
|
};
|
|
176
231
|
onPaymentSettled(logEntry);
|
|
232
|
+
if (telemetry) {
|
|
233
|
+
const event = createTelemetryEvent(logEntry, telemetry);
|
|
234
|
+
sendTelemetry(event, telemetry.endpoint).catch(
|
|
235
|
+
(err) => console.error("[x402-telemetry] Async send failed:", err)
|
|
236
|
+
);
|
|
237
|
+
}
|
|
177
238
|
} catch (err) {
|
|
178
239
|
console.error(
|
|
179
240
|
"[x402-mantle-sdk] Error calling onPaymentSettled hook:",
|
|
@@ -300,7 +361,8 @@ function createPaymentClient(config) {
|
|
|
300
361
|
resourceUrl,
|
|
301
362
|
facilitatorUrl,
|
|
302
363
|
provider,
|
|
303
|
-
userAddress: userAddressOverride
|
|
364
|
+
userAddress: userAddressOverride,
|
|
365
|
+
projectKey
|
|
304
366
|
} = config;
|
|
305
367
|
if (!resourceUrl) {
|
|
306
368
|
throw new Error("resourceUrl is required");
|
|
@@ -387,7 +449,8 @@ function createPaymentClient(config) {
|
|
|
387
449
|
const settleRes = await fetch(settleUrl, {
|
|
388
450
|
method: "POST",
|
|
389
451
|
headers: {
|
|
390
|
-
"Content-Type": "application/json"
|
|
452
|
+
"Content-Type": "application/json",
|
|
453
|
+
...projectKey ? { "X-Project-Key": projectKey } : {}
|
|
391
454
|
},
|
|
392
455
|
body: JSON.stringify({
|
|
393
456
|
x402Version: 1,
|
package/dist/index.d.cts
CHANGED
|
@@ -64,8 +64,39 @@ interface PaymentLogEntry {
|
|
|
64
64
|
route?: RouteKey;
|
|
65
65
|
txHash?: string;
|
|
66
66
|
timestamp: number;
|
|
67
|
+
facilitatorUrl?: string;
|
|
67
68
|
paymentRequirements?: PaymentRequirements;
|
|
68
69
|
}
|
|
70
|
+
/** Config for optional telemetry (billing/analytics). */
|
|
71
|
+
interface TelemetryConfig {
|
|
72
|
+
/** Project key from nosubs.ai dashboard. */
|
|
73
|
+
projectKey: string;
|
|
74
|
+
/**
|
|
75
|
+
* Telemetry endpoint URL.
|
|
76
|
+
* If not specified, uses DEFAULT_TELEMETRY_ENDPOINT (see server/constants.ts).
|
|
77
|
+
* If both are undefined, telemetry is not sent.
|
|
78
|
+
*/
|
|
79
|
+
endpoint?: string;
|
|
80
|
+
}
|
|
81
|
+
/** Telemetry event payload for payment_verified. */
|
|
82
|
+
interface TelemetryEvent {
|
|
83
|
+
event: "payment_verified";
|
|
84
|
+
ts: number;
|
|
85
|
+
projectKey: string;
|
|
86
|
+
network: string;
|
|
87
|
+
buyer: string;
|
|
88
|
+
payTo: string;
|
|
89
|
+
amountAtomic: string;
|
|
90
|
+
asset: string;
|
|
91
|
+
decimals: number;
|
|
92
|
+
nonce: string;
|
|
93
|
+
route: string;
|
|
94
|
+
facilitatorType: "hosted" | "self-hosted";
|
|
95
|
+
facilitatorUrl?: string;
|
|
96
|
+
facilitatorAddress?: string;
|
|
97
|
+
txHash?: string;
|
|
98
|
+
priceUsd?: string;
|
|
99
|
+
}
|
|
69
100
|
/** Config for createPaymentMiddleware. */
|
|
70
101
|
interface PaymentMiddlewareConfig {
|
|
71
102
|
/** Base URL of facilitator, e.g. https://facilitator.nosubs.ai */
|
|
@@ -79,6 +110,8 @@ interface PaymentMiddlewareConfig {
|
|
|
79
110
|
* You can use this to push logs into your DB / analytics pipeline.
|
|
80
111
|
*/
|
|
81
112
|
onPaymentSettled?: (entry: PaymentLogEntry) => void;
|
|
113
|
+
/** Optional: Send usage telemetry for billing/analytics. */
|
|
114
|
+
telemetry?: TelemetryConfig;
|
|
82
115
|
}
|
|
83
116
|
|
|
84
117
|
declare function createPaymentMiddleware(config: PaymentMiddlewareConfig): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
@@ -93,6 +126,8 @@ interface PaymentClientConfig {
|
|
|
93
126
|
provider: unknown;
|
|
94
127
|
/** Optional user address override; otherwise derived from provider. */
|
|
95
128
|
userAddress?: string;
|
|
129
|
+
/** Optional: Project key for hosted facilitator billing. */
|
|
130
|
+
projectKey?: string;
|
|
96
131
|
}
|
|
97
132
|
/** Result of a callWithPayment() client operation. */
|
|
98
133
|
interface CallWithPaymentResult<TResponseBody = unknown> {
|
|
@@ -122,8 +157,8 @@ interface PaymentClient {
|
|
|
122
157
|
* - calls facilitator /settle
|
|
123
158
|
* - retries the original request with X-PAYMENT header
|
|
124
159
|
*
|
|
125
|
-
* This logic is x402
|
|
160
|
+
* This logic is x402 and tailored for Mantle + USDC.
|
|
126
161
|
*/
|
|
127
162
|
declare function createPaymentClient(config: PaymentClientConfig): PaymentClient;
|
|
128
163
|
|
|
129
|
-
export { type AssetConfig, type Authorization, type CallWithPaymentResult, type NetworkId, type PaymentClient, type PaymentClientConfig, type PaymentHeaderBase64, type PaymentHeaderObject, type PaymentHeaderPayload, type PaymentLogEntry, type PaymentMiddlewareConfig, type PaymentRequirements, type RouteKey, type RoutePricingConfig, type RoutesConfig, createPaymentClient, createPaymentMiddleware };
|
|
164
|
+
export { type AssetConfig, type Authorization, type CallWithPaymentResult, type NetworkId, type PaymentClient, type PaymentClientConfig, type PaymentHeaderBase64, type PaymentHeaderObject, type PaymentHeaderPayload, type PaymentLogEntry, type PaymentMiddlewareConfig, type PaymentRequirements, type RouteKey, type RoutePricingConfig, type RoutesConfig, type TelemetryConfig, type TelemetryEvent, createPaymentClient, createPaymentMiddleware };
|
package/dist/index.d.ts
CHANGED
|
@@ -64,8 +64,39 @@ interface PaymentLogEntry {
|
|
|
64
64
|
route?: RouteKey;
|
|
65
65
|
txHash?: string;
|
|
66
66
|
timestamp: number;
|
|
67
|
+
facilitatorUrl?: string;
|
|
67
68
|
paymentRequirements?: PaymentRequirements;
|
|
68
69
|
}
|
|
70
|
+
/** Config for optional telemetry (billing/analytics). */
|
|
71
|
+
interface TelemetryConfig {
|
|
72
|
+
/** Project key from nosubs.ai dashboard. */
|
|
73
|
+
projectKey: string;
|
|
74
|
+
/**
|
|
75
|
+
* Telemetry endpoint URL.
|
|
76
|
+
* If not specified, uses DEFAULT_TELEMETRY_ENDPOINT (see server/constants.ts).
|
|
77
|
+
* If both are undefined, telemetry is not sent.
|
|
78
|
+
*/
|
|
79
|
+
endpoint?: string;
|
|
80
|
+
}
|
|
81
|
+
/** Telemetry event payload for payment_verified. */
|
|
82
|
+
interface TelemetryEvent {
|
|
83
|
+
event: "payment_verified";
|
|
84
|
+
ts: number;
|
|
85
|
+
projectKey: string;
|
|
86
|
+
network: string;
|
|
87
|
+
buyer: string;
|
|
88
|
+
payTo: string;
|
|
89
|
+
amountAtomic: string;
|
|
90
|
+
asset: string;
|
|
91
|
+
decimals: number;
|
|
92
|
+
nonce: string;
|
|
93
|
+
route: string;
|
|
94
|
+
facilitatorType: "hosted" | "self-hosted";
|
|
95
|
+
facilitatorUrl?: string;
|
|
96
|
+
facilitatorAddress?: string;
|
|
97
|
+
txHash?: string;
|
|
98
|
+
priceUsd?: string;
|
|
99
|
+
}
|
|
69
100
|
/** Config for createPaymentMiddleware. */
|
|
70
101
|
interface PaymentMiddlewareConfig {
|
|
71
102
|
/** Base URL of facilitator, e.g. https://facilitator.nosubs.ai */
|
|
@@ -79,6 +110,8 @@ interface PaymentMiddlewareConfig {
|
|
|
79
110
|
* You can use this to push logs into your DB / analytics pipeline.
|
|
80
111
|
*/
|
|
81
112
|
onPaymentSettled?: (entry: PaymentLogEntry) => void;
|
|
113
|
+
/** Optional: Send usage telemetry for billing/analytics. */
|
|
114
|
+
telemetry?: TelemetryConfig;
|
|
82
115
|
}
|
|
83
116
|
|
|
84
117
|
declare function createPaymentMiddleware(config: PaymentMiddlewareConfig): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
@@ -93,6 +126,8 @@ interface PaymentClientConfig {
|
|
|
93
126
|
provider: unknown;
|
|
94
127
|
/** Optional user address override; otherwise derived from provider. */
|
|
95
128
|
userAddress?: string;
|
|
129
|
+
/** Optional: Project key for hosted facilitator billing. */
|
|
130
|
+
projectKey?: string;
|
|
96
131
|
}
|
|
97
132
|
/** Result of a callWithPayment() client operation. */
|
|
98
133
|
interface CallWithPaymentResult<TResponseBody = unknown> {
|
|
@@ -122,8 +157,8 @@ interface PaymentClient {
|
|
|
122
157
|
* - calls facilitator /settle
|
|
123
158
|
* - retries the original request with X-PAYMENT header
|
|
124
159
|
*
|
|
125
|
-
* This logic is x402
|
|
160
|
+
* This logic is x402 and tailored for Mantle + USDC.
|
|
126
161
|
*/
|
|
127
162
|
declare function createPaymentClient(config: PaymentClientConfig): PaymentClient;
|
|
128
163
|
|
|
129
|
-
export { type AssetConfig, type Authorization, type CallWithPaymentResult, type NetworkId, type PaymentClient, type PaymentClientConfig, type PaymentHeaderBase64, type PaymentHeaderObject, type PaymentHeaderPayload, type PaymentLogEntry, type PaymentMiddlewareConfig, type PaymentRequirements, type RouteKey, type RoutePricingConfig, type RoutesConfig, createPaymentClient, createPaymentMiddleware };
|
|
164
|
+
export { type AssetConfig, type Authorization, type CallWithPaymentResult, type NetworkId, type PaymentClient, type PaymentClientConfig, type PaymentHeaderBase64, type PaymentHeaderObject, type PaymentHeaderPayload, type PaymentLogEntry, type PaymentMiddlewareConfig, type PaymentRequirements, type RouteKey, type RoutePricingConfig, type RoutesConfig, type TelemetryConfig, type TelemetryEvent, createPaymentClient, createPaymentMiddleware };
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,59 @@ function usdCentsToAtomic(cents, decimals) {
|
|
|
38
38
|
return BigInt(cents) * base;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
// src/server/constants.ts
|
|
42
|
+
var DEFAULT_TELEMETRY_ENDPOINT = void 0;
|
|
43
|
+
|
|
44
|
+
// src/server/telemetry.ts
|
|
45
|
+
function createTelemetryEvent(entry, config) {
|
|
46
|
+
const assetConfig = getDefaultAssetForNetwork(entry.network);
|
|
47
|
+
return {
|
|
48
|
+
event: "payment_verified",
|
|
49
|
+
ts: entry.timestamp,
|
|
50
|
+
projectKey: config.projectKey,
|
|
51
|
+
network: entry.network,
|
|
52
|
+
buyer: entry.from,
|
|
53
|
+
payTo: entry.to,
|
|
54
|
+
amountAtomic: entry.valueAtomic,
|
|
55
|
+
asset: entry.asset,
|
|
56
|
+
decimals: assetConfig.decimals,
|
|
57
|
+
nonce: entry.id,
|
|
58
|
+
route: entry.route ?? "unknown",
|
|
59
|
+
// Facilitator metadata
|
|
60
|
+
facilitatorType: "hosted",
|
|
61
|
+
// SDK always uses hosted mode
|
|
62
|
+
facilitatorUrl: entry.facilitatorUrl,
|
|
63
|
+
// From PaymentLogEntry
|
|
64
|
+
// facilitatorAddress is undefined for SDK (not available)
|
|
65
|
+
// Optional metadata
|
|
66
|
+
txHash: entry.txHash,
|
|
67
|
+
priceUsd: entry.paymentRequirements?.price
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async function sendTelemetry(event, endpoint) {
|
|
71
|
+
const targetEndpoint = endpoint ?? DEFAULT_TELEMETRY_ENDPOINT;
|
|
72
|
+
if (!targetEndpoint) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const response = await fetch(targetEndpoint, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: {
|
|
79
|
+
"Content-Type": "application/json",
|
|
80
|
+
"Authorization": `Bearer ${event.projectKey}`
|
|
81
|
+
},
|
|
82
|
+
body: JSON.stringify(event)
|
|
83
|
+
});
|
|
84
|
+
if (!response.ok) {
|
|
85
|
+
console.warn(
|
|
86
|
+
`[x402-telemetry] Failed to send event: HTTP ${response.status}`
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
} catch (err) {
|
|
90
|
+
console.error("[x402-telemetry] Error sending telemetry:", err);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
41
94
|
// src/server/paymentMiddleware.ts
|
|
42
95
|
function getRouteKey(req) {
|
|
43
96
|
const method = (req.method || "GET").toUpperCase();
|
|
@@ -61,7 +114,7 @@ function decodePaymentHeader(paymentHeaderBase64) {
|
|
|
61
114
|
}
|
|
62
115
|
}
|
|
63
116
|
function createPaymentMiddleware(config) {
|
|
64
|
-
const { facilitatorUrl, receiverAddress, routes, onPaymentSettled } = config;
|
|
117
|
+
const { facilitatorUrl, receiverAddress, routes, onPaymentSettled, telemetry } = config;
|
|
65
118
|
if (!facilitatorUrl) {
|
|
66
119
|
throw new Error("facilitatorUrl is required");
|
|
67
120
|
}
|
|
@@ -151,9 +204,17 @@ function createPaymentMiddleware(config) {
|
|
|
151
204
|
asset: assetConfig.address,
|
|
152
205
|
route: routeKey,
|
|
153
206
|
timestamp: Date.now(),
|
|
207
|
+
facilitatorUrl,
|
|
208
|
+
// Pass from config closure
|
|
154
209
|
paymentRequirements
|
|
155
210
|
};
|
|
156
211
|
onPaymentSettled(logEntry);
|
|
212
|
+
if (telemetry) {
|
|
213
|
+
const event = createTelemetryEvent(logEntry, telemetry);
|
|
214
|
+
sendTelemetry(event, telemetry.endpoint).catch(
|
|
215
|
+
(err) => console.error("[x402-telemetry] Async send failed:", err)
|
|
216
|
+
);
|
|
217
|
+
}
|
|
157
218
|
} catch (err) {
|
|
158
219
|
console.error(
|
|
159
220
|
"[x402-mantle-sdk] Error calling onPaymentSettled hook:",
|
|
@@ -280,7 +341,8 @@ function createPaymentClient(config) {
|
|
|
280
341
|
resourceUrl,
|
|
281
342
|
facilitatorUrl,
|
|
282
343
|
provider,
|
|
283
|
-
userAddress: userAddressOverride
|
|
344
|
+
userAddress: userAddressOverride,
|
|
345
|
+
projectKey
|
|
284
346
|
} = config;
|
|
285
347
|
if (!resourceUrl) {
|
|
286
348
|
throw new Error("resourceUrl is required");
|
|
@@ -367,7 +429,8 @@ function createPaymentClient(config) {
|
|
|
367
429
|
const settleRes = await fetch(settleUrl, {
|
|
368
430
|
method: "POST",
|
|
369
431
|
headers: {
|
|
370
|
-
"Content-Type": "application/json"
|
|
432
|
+
"Content-Type": "application/json",
|
|
433
|
+
...projectKey ? { "X-Project-Key": projectKey } : {}
|
|
371
434
|
},
|
|
372
435
|
body: JSON.stringify({
|
|
373
436
|
x402Version: 1,
|
package/package.json
CHANGED