@agentspend/sdk 0.3.2 → 0.3.3
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.js +48 -2
- package/package.json +1 -1
- package/src/index.ts +48 -2
package/dist/index.js
CHANGED
|
@@ -42,6 +42,27 @@ function createAgentSpend(options) {
|
|
|
42
42
|
}
|
|
43
43
|
const platformApiBaseUrl = resolvePlatformApiBaseUrl(options.platformApiBaseUrl);
|
|
44
44
|
// -------------------------------------------------------------------
|
|
45
|
+
// Lazy service_id fetch + cache
|
|
46
|
+
// -------------------------------------------------------------------
|
|
47
|
+
let cachedServiceId = null;
|
|
48
|
+
async function getServiceId() {
|
|
49
|
+
if (cachedServiceId)
|
|
50
|
+
return cachedServiceId;
|
|
51
|
+
if (!options.serviceApiKey)
|
|
52
|
+
return null;
|
|
53
|
+
try {
|
|
54
|
+
const res = await fetchImpl(joinUrl(platformApiBaseUrl, "/v1/service/me"), {
|
|
55
|
+
headers: { authorization: `Bearer ${options.serviceApiKey}` }
|
|
56
|
+
});
|
|
57
|
+
if (res.ok) {
|
|
58
|
+
const data = (await res.json());
|
|
59
|
+
cachedServiceId = data.id ?? null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch { /* graceful fallback */ }
|
|
63
|
+
return cachedServiceId;
|
|
64
|
+
}
|
|
65
|
+
// -------------------------------------------------------------------
|
|
45
66
|
// x402 singleton setup (Decision 9)
|
|
46
67
|
// Server-side: facilitator handles verify + settle over HTTP.
|
|
47
68
|
// No client-side EVM scheme needed — we delegate to the facilitator.
|
|
@@ -167,6 +188,10 @@ function createAgentSpend(options) {
|
|
|
167
188
|
}
|
|
168
189
|
catch (error) {
|
|
169
190
|
if (error instanceof AgentSpendChargeError) {
|
|
191
|
+
if (error.statusCode === 403) {
|
|
192
|
+
// No binding — return 402 so agent can discover service_id and bind
|
|
193
|
+
return return402Response(c, amountCents, currency);
|
|
194
|
+
}
|
|
170
195
|
if (error.statusCode === 402) {
|
|
171
196
|
return c.json({ error: "Payment required", details: error.details }, 402);
|
|
172
197
|
}
|
|
@@ -236,6 +261,7 @@ function createAgentSpend(options) {
|
|
|
236
261
|
// return402Response — x402 Payment-Required format (Decision 8)
|
|
237
262
|
// -------------------------------------------------------------------
|
|
238
263
|
async function return402Response(c, amountCents, currency) {
|
|
264
|
+
const serviceId = await getServiceId();
|
|
239
265
|
try {
|
|
240
266
|
const payTo = await resolvePayToAddress();
|
|
241
267
|
const paymentRequirements = {
|
|
@@ -261,11 +287,31 @@ function createAgentSpend(options) {
|
|
|
261
287
|
// Set Payment-Required header (base64 encoded)
|
|
262
288
|
const headerValue = Buffer.from(JSON.stringify(paymentRequired)).toString("base64");
|
|
263
289
|
c.header("Payment-Required", headerValue);
|
|
264
|
-
return c.json({
|
|
290
|
+
return c.json({
|
|
291
|
+
error: "Payment required",
|
|
292
|
+
amount_cents: amountCents,
|
|
293
|
+
currency,
|
|
294
|
+
...(serviceId ? {
|
|
295
|
+
agentspend: {
|
|
296
|
+
service_id: serviceId,
|
|
297
|
+
amount_cents: amountCents,
|
|
298
|
+
}
|
|
299
|
+
} : {})
|
|
300
|
+
}, 402);
|
|
265
301
|
}
|
|
266
302
|
catch {
|
|
267
303
|
// If we can't resolve a payTo address, return a plain 402
|
|
268
|
-
return c.json({
|
|
304
|
+
return c.json({
|
|
305
|
+
error: "Payment required",
|
|
306
|
+
amount_cents: amountCents,
|
|
307
|
+
currency,
|
|
308
|
+
...(serviceId ? {
|
|
309
|
+
agentspend: {
|
|
310
|
+
service_id: serviceId,
|
|
311
|
+
amount_cents: amountCents,
|
|
312
|
+
}
|
|
313
|
+
} : {})
|
|
314
|
+
}, 402);
|
|
269
315
|
}
|
|
270
316
|
}
|
|
271
317
|
// -------------------------------------------------------------------
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -170,6 +170,26 @@ export function createAgentSpend(options: AgentSpendOptions): AgentSpend {
|
|
|
170
170
|
|
|
171
171
|
const platformApiBaseUrl = resolvePlatformApiBaseUrl(options.platformApiBaseUrl);
|
|
172
172
|
|
|
173
|
+
// -------------------------------------------------------------------
|
|
174
|
+
// Lazy service_id fetch + cache
|
|
175
|
+
// -------------------------------------------------------------------
|
|
176
|
+
let cachedServiceId: string | null = null;
|
|
177
|
+
|
|
178
|
+
async function getServiceId(): Promise<string | null> {
|
|
179
|
+
if (cachedServiceId) return cachedServiceId;
|
|
180
|
+
if (!options.serviceApiKey) return null;
|
|
181
|
+
try {
|
|
182
|
+
const res = await fetchImpl(joinUrl(platformApiBaseUrl, "/v1/service/me"), {
|
|
183
|
+
headers: { authorization: `Bearer ${options.serviceApiKey}` }
|
|
184
|
+
});
|
|
185
|
+
if (res.ok) {
|
|
186
|
+
const data = (await res.json()) as { id?: string };
|
|
187
|
+
cachedServiceId = data.id ?? null;
|
|
188
|
+
}
|
|
189
|
+
} catch { /* graceful fallback */ }
|
|
190
|
+
return cachedServiceId;
|
|
191
|
+
}
|
|
192
|
+
|
|
173
193
|
// -------------------------------------------------------------------
|
|
174
194
|
// x402 singleton setup (Decision 9)
|
|
175
195
|
// Server-side: facilitator handles verify + settle over HTTP.
|
|
@@ -336,6 +356,10 @@ export function createAgentSpend(options: AgentSpendOptions): AgentSpend {
|
|
|
336
356
|
c.set(PAYMENT_CONTEXT_KEY, paymentContext);
|
|
337
357
|
} catch (error) {
|
|
338
358
|
if (error instanceof AgentSpendChargeError) {
|
|
359
|
+
if (error.statusCode === 403) {
|
|
360
|
+
// No binding — return 402 so agent can discover service_id and bind
|
|
361
|
+
return return402Response(c, amountCents, currency);
|
|
362
|
+
}
|
|
339
363
|
if (error.statusCode === 402) {
|
|
340
364
|
return c.json({ error: "Payment required", details: error.details }, 402);
|
|
341
365
|
}
|
|
@@ -446,6 +470,8 @@ export function createAgentSpend(options: AgentSpendOptions): AgentSpend {
|
|
|
446
470
|
amountCents: number,
|
|
447
471
|
currency: string
|
|
448
472
|
): Promise<Response> {
|
|
473
|
+
const serviceId = await getServiceId();
|
|
474
|
+
|
|
449
475
|
try {
|
|
450
476
|
const payTo = await resolvePayToAddress();
|
|
451
477
|
|
|
@@ -477,11 +503,31 @@ export function createAgentSpend(options: AgentSpendOptions): AgentSpend {
|
|
|
477
503
|
).toString("base64");
|
|
478
504
|
c.header("Payment-Required", headerValue);
|
|
479
505
|
|
|
480
|
-
return c.json({
|
|
506
|
+
return c.json({
|
|
507
|
+
error: "Payment required",
|
|
508
|
+
amount_cents: amountCents,
|
|
509
|
+
currency,
|
|
510
|
+
...(serviceId ? {
|
|
511
|
+
agentspend: {
|
|
512
|
+
service_id: serviceId,
|
|
513
|
+
amount_cents: amountCents,
|
|
514
|
+
}
|
|
515
|
+
} : {})
|
|
516
|
+
}, 402);
|
|
481
517
|
} catch {
|
|
482
518
|
// If we can't resolve a payTo address, return a plain 402
|
|
483
519
|
return c.json(
|
|
484
|
-
{
|
|
520
|
+
{
|
|
521
|
+
error: "Payment required",
|
|
522
|
+
amount_cents: amountCents,
|
|
523
|
+
currency,
|
|
524
|
+
...(serviceId ? {
|
|
525
|
+
agentspend: {
|
|
526
|
+
service_id: serviceId,
|
|
527
|
+
amount_cents: amountCents,
|
|
528
|
+
}
|
|
529
|
+
} : {})
|
|
530
|
+
},
|
|
485
531
|
402
|
|
486
532
|
);
|
|
487
533
|
}
|