s402 0.1.7 → 0.1.8
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 +2 -0
- package/dist/http.d.mts +26 -1
- package/dist/http.mjs +66 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
**Sui-native HTTP 402 protocol.** Atomic settlement via Sui's Programmable Transaction Blocks (PTBs). Includes an optional compat layer (`s402/compat`) for normalizing x402 input.
|
|
7
7
|
|
|
8
|
+
s402 is the Sui-native implementation of HTTP 402 (Payment Required) — an open protocol that lets AI agents pay for API calls in a single HTTP request with no per-call on-chain transaction. Unlike Coinbase's x402 on Ethereum, s402 uses Sui's Programmable Transaction Blocks to reduce 1,000 payments to just 2 on-chain transactions via the Prepaid scheme, cutting per-call effective gas from $0.007 to $0.000014 and making micropayments economically viable for AI agents for the first time.
|
|
9
|
+
|
|
8
10
|
```bash
|
|
9
11
|
npm install s402
|
|
10
12
|
pnpm add s402
|
package/dist/http.d.mts
CHANGED
|
@@ -74,6 +74,31 @@ declare function validatePrepaidShape(value: unknown): void;
|
|
|
74
74
|
declare function validateSubObjects(record: Record<string, unknown>): void;
|
|
75
75
|
/** Validate that decoded payment requirements have the required shape. */
|
|
76
76
|
declare function validateRequirementsShape(obj: unknown): void;
|
|
77
|
+
/** Content type for s402 JSON body transport */
|
|
78
|
+
declare const S402_CONTENT_TYPE: "application/s402+json";
|
|
79
|
+
/** Encode payment requirements as JSON string (for response body) */
|
|
80
|
+
declare function encodeRequirementsBody(requirements: s402PaymentRequirements): string;
|
|
81
|
+
/** Decode payment requirements from JSON string (from response body) */
|
|
82
|
+
declare function decodeRequirementsBody(body: string): s402PaymentRequirements;
|
|
83
|
+
/** Encode payment payload as JSON string (for request body) */
|
|
84
|
+
declare function encodePayloadBody(payload: s402PaymentPayload): string;
|
|
85
|
+
/** Decode payment payload from JSON string (from request body) */
|
|
86
|
+
declare function decodePayloadBody(body: string): s402PaymentPayload;
|
|
87
|
+
/** Encode settlement response as JSON string (for response body) */
|
|
88
|
+
declare function encodeSettleBody(response: s402SettleResponse): string;
|
|
89
|
+
/** Decode settlement response from JSON string (from response body) */
|
|
90
|
+
declare function decodeSettleBody(body: string): s402SettleResponse;
|
|
91
|
+
/**
|
|
92
|
+
* Detect transport mode from an incoming request.
|
|
93
|
+
*
|
|
94
|
+
* Checks Content-Type for body transport, then falls back to header detection.
|
|
95
|
+
* Returns 'body' if Content-Type is application/s402+json.
|
|
96
|
+
* Returns 'header' if x-payment header is present.
|
|
97
|
+
* Returns 'unknown' otherwise.
|
|
98
|
+
*/
|
|
99
|
+
declare function detectTransport(request: {
|
|
100
|
+
headers: Headers;
|
|
101
|
+
}): 'header' | 'body' | 'unknown';
|
|
77
102
|
/**
|
|
78
103
|
* Detect whether a 402 response uses s402 or x402 protocol.
|
|
79
104
|
*
|
|
@@ -88,4 +113,4 @@ declare function detectProtocol(headers: Headers): 's402' | 'x402' | 'unknown';
|
|
|
88
113
|
*/
|
|
89
114
|
declare function extractRequirementsFromResponse(response: Response): s402PaymentRequirements | null;
|
|
90
115
|
//#endregion
|
|
91
|
-
export { decodePaymentPayload, decodePaymentRequired, decodeSettleResponse, detectProtocol, encodePaymentPayload, encodePaymentRequired, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, pickPayloadFields, pickRequirementsFields, pickSettleResponseFields, validateEscrowShape, validateMandateShape, validatePrepaidShape, validateRequirementsShape, validateStreamShape, validateSubObjects, validateUnlockShape };
|
|
116
|
+
export { S402_CONTENT_TYPE, decodePayloadBody, decodePaymentPayload, decodePaymentRequired, decodeRequirementsBody, decodeSettleBody, decodeSettleResponse, detectProtocol, detectTransport, encodePayloadBody, encodePaymentPayload, encodePaymentRequired, encodeRequirementsBody, encodeSettleBody, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, pickPayloadFields, pickRequirementsFields, pickSettleResponseFields, validateEscrowShape, validateMandateShape, validatePrepaidShape, validateRequirementsShape, validateStreamShape, validateSubObjects, validateUnlockShape };
|
package/dist/http.mjs
CHANGED
|
@@ -83,7 +83,9 @@ const S402_SUB_OBJECT_KEYS = {
|
|
|
83
83
|
"ratePerCall",
|
|
84
84
|
"maxCalls",
|
|
85
85
|
"minDeposit",
|
|
86
|
-
"withdrawalDelayMs"
|
|
86
|
+
"withdrawalDelayMs",
|
|
87
|
+
"providerPubkey",
|
|
88
|
+
"disputeWindowMs"
|
|
87
89
|
])
|
|
88
90
|
};
|
|
89
91
|
/** Strip unknown keys from a sub-object, returning a clean copy. */
|
|
@@ -318,6 +320,8 @@ function validatePrepaidShape(value) {
|
|
|
318
320
|
assertString(obj, "withdrawalDelayMs", "prepaid");
|
|
319
321
|
if (typeof obj.withdrawalDelayMs === "string" && !isValidAmount(obj.withdrawalDelayMs)) throw new s402Error("INVALID_PAYLOAD", `prepaid.withdrawalDelayMs must be a non-negative integer string (milliseconds), got "${obj.withdrawalDelayMs}"`);
|
|
320
322
|
assertOptionalString(obj, "maxCalls", "prepaid");
|
|
323
|
+
assertOptionalString(obj, "providerPubkey", "prepaid");
|
|
324
|
+
assertOptionalString(obj, "disputeWindowMs", "prepaid");
|
|
321
325
|
}
|
|
322
326
|
/**
|
|
323
327
|
* Validate all optional sub-objects on a requirements record.
|
|
@@ -386,6 +390,66 @@ function validateSettleShape(obj) {
|
|
|
386
390
|
if (obj == null || typeof obj !== "object") throw new s402Error("INVALID_PAYLOAD", "Settle response is not an object");
|
|
387
391
|
if (typeof obj.success !== "boolean") throw new s402Error("INVALID_PAYLOAD", "Malformed settle response: missing or invalid \"success\" (boolean)");
|
|
388
392
|
}
|
|
393
|
+
/** Content type for s402 JSON body transport */
|
|
394
|
+
const S402_CONTENT_TYPE = "application/s402+json";
|
|
395
|
+
/** Encode payment requirements as JSON string (for response body) */
|
|
396
|
+
function encodeRequirementsBody(requirements) {
|
|
397
|
+
return JSON.stringify(requirements);
|
|
398
|
+
}
|
|
399
|
+
/** Decode payment requirements from JSON string (from response body) */
|
|
400
|
+
function decodeRequirementsBody(body) {
|
|
401
|
+
let parsed;
|
|
402
|
+
try {
|
|
403
|
+
parsed = JSON.parse(body);
|
|
404
|
+
} catch (e) {
|
|
405
|
+
throw new s402Error("INVALID_PAYLOAD", `Failed to parse s402 requirements body: ${e instanceof Error ? e.message : "invalid JSON"}`);
|
|
406
|
+
}
|
|
407
|
+
validateRequirementsShape(parsed);
|
|
408
|
+
return pickRequirementsFields(parsed);
|
|
409
|
+
}
|
|
410
|
+
/** Encode payment payload as JSON string (for request body) */
|
|
411
|
+
function encodePayloadBody(payload) {
|
|
412
|
+
return JSON.stringify(payload);
|
|
413
|
+
}
|
|
414
|
+
/** Decode payment payload from JSON string (from request body) */
|
|
415
|
+
function decodePayloadBody(body) {
|
|
416
|
+
let parsed;
|
|
417
|
+
try {
|
|
418
|
+
parsed = JSON.parse(body);
|
|
419
|
+
} catch (e) {
|
|
420
|
+
throw new s402Error("INVALID_PAYLOAD", `Failed to parse s402 payload body: ${e instanceof Error ? e.message : "invalid JSON"}`);
|
|
421
|
+
}
|
|
422
|
+
validatePayloadShape(parsed);
|
|
423
|
+
return pickPayloadFields(parsed);
|
|
424
|
+
}
|
|
425
|
+
/** Encode settlement response as JSON string (for response body) */
|
|
426
|
+
function encodeSettleBody(response) {
|
|
427
|
+
return JSON.stringify(response);
|
|
428
|
+
}
|
|
429
|
+
/** Decode settlement response from JSON string (from response body) */
|
|
430
|
+
function decodeSettleBody(body) {
|
|
431
|
+
let parsed;
|
|
432
|
+
try {
|
|
433
|
+
parsed = JSON.parse(body);
|
|
434
|
+
} catch (e) {
|
|
435
|
+
throw new s402Error("INVALID_PAYLOAD", `Failed to parse s402 settle body: ${e instanceof Error ? e.message : "invalid JSON"}`);
|
|
436
|
+
}
|
|
437
|
+
validateSettleShape(parsed);
|
|
438
|
+
return pickSettleResponseFields(parsed);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Detect transport mode from an incoming request.
|
|
442
|
+
*
|
|
443
|
+
* Checks Content-Type for body transport, then falls back to header detection.
|
|
444
|
+
* Returns 'body' if Content-Type is application/s402+json.
|
|
445
|
+
* Returns 'header' if x-payment header is present.
|
|
446
|
+
* Returns 'unknown' otherwise.
|
|
447
|
+
*/
|
|
448
|
+
function detectTransport(request) {
|
|
449
|
+
if (request.headers.get("content-type")?.includes(S402_CONTENT_TYPE)) return "body";
|
|
450
|
+
if (request.headers.get(S402_HEADERS.PAYMENT)) return "header";
|
|
451
|
+
return "unknown";
|
|
452
|
+
}
|
|
389
453
|
/**
|
|
390
454
|
* Detect whether a 402 response uses s402 or x402 protocol.
|
|
391
455
|
*
|
|
@@ -421,4 +485,4 @@ function extractRequirementsFromResponse(response) {
|
|
|
421
485
|
}
|
|
422
486
|
|
|
423
487
|
//#endregion
|
|
424
|
-
export { decodePaymentPayload, decodePaymentRequired, decodeSettleResponse, detectProtocol, encodePaymentPayload, encodePaymentRequired, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, pickPayloadFields, pickRequirementsFields, pickSettleResponseFields, validateEscrowShape, validateMandateShape, validatePrepaidShape, validateRequirementsShape, validateStreamShape, validateSubObjects, validateUnlockShape };
|
|
488
|
+
export { S402_CONTENT_TYPE, decodePayloadBody, decodePaymentPayload, decodePaymentRequired, decodeRequirementsBody, decodeSettleBody, decodeSettleResponse, detectProtocol, detectTransport, encodePayloadBody, encodePaymentPayload, encodePaymentRequired, encodeRequirementsBody, encodeSettleBody, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, pickPayloadFields, pickRequirementsFields, pickSettleResponseFields, validateEscrowShape, validateMandateShape, validatePrepaidShape, validateRequirementsShape, validateStreamShape, validateSubObjects, validateUnlockShape };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createS402Error, s402Error, s402ErrorCode, s402ErrorCodeType, s402ErrorInfo } from "./errors.mjs";
|
|
2
2
|
import { S402_HEADERS, S402_VERSION, s402Discovery, s402EscrowExtra, s402EscrowPayload, s402ExactPayload, s402Mandate, s402MandateRequirements, s402PaymentPayload, s402PaymentPayloadBase, s402PaymentRequirements, s402PaymentSession, s402PrepaidExtra, s402PrepaidPayload, s402RegistryQuery, s402Scheme, s402ServiceEntry, s402SettleResponse, s402SettlementMode, s402StreamExtra, s402StreamPayload, s402UnlockExtra, s402UnlockPayload, s402VerifyResponse } from "./types.mjs";
|
|
3
|
-
import { decodePaymentPayload, decodePaymentRequired, decodeSettleResponse, detectProtocol, encodePaymentPayload, encodePaymentRequired, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, validateRequirementsShape } from "./http.mjs";
|
|
3
|
+
import { S402_CONTENT_TYPE, decodePayloadBody, decodePaymentPayload, decodePaymentRequired, decodeRequirementsBody, decodeSettleBody, decodeSettleResponse, detectProtocol, detectTransport, encodePayloadBody, encodePaymentPayload, encodePaymentRequired, encodeRequirementsBody, encodeSettleBody, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, validateRequirementsShape } from "./http.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/scheme.d.ts
|
|
6
6
|
/** Implemented by each scheme on the client side */
|
|
@@ -192,4 +192,4 @@ declare class s402ResourceServer {
|
|
|
192
192
|
process(payload: s402PaymentPayload, requirements: s402PaymentRequirements): Promise<s402SettleResponse>;
|
|
193
193
|
}
|
|
194
194
|
//#endregion
|
|
195
|
-
export { S402_HEADERS, S402_VERSION, createS402Error, decodePaymentPayload, decodePaymentRequired, decodeSettleResponse, detectProtocol, encodePaymentPayload, encodePaymentRequired, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, s402Client, type s402ClientScheme, type s402DirectScheme, type s402Discovery, s402Error, s402ErrorCode, type s402ErrorCodeType, type s402ErrorInfo, type s402EscrowExtra, type s402EscrowPayload, type s402ExactPayload, s402Facilitator, type s402FacilitatorScheme, type s402Mandate, type s402MandateRequirements, type s402PaymentPayload, type s402PaymentPayloadBase, type s402PaymentRequirements, type s402PaymentSession, type s402PrepaidExtra, type s402PrepaidPayload, type s402RegistryQuery, s402ResourceServer, type s402RouteConfig, type s402Scheme, type s402ServerScheme, type s402ServiceEntry, type s402SettleResponse, type s402SettlementMode, type s402StreamExtra, type s402StreamPayload, type s402UnlockExtra, type s402UnlockPayload, type s402VerifyResponse, validateRequirementsShape };
|
|
195
|
+
export { S402_CONTENT_TYPE, S402_HEADERS, S402_VERSION, createS402Error, decodePayloadBody, decodePaymentPayload, decodePaymentRequired, decodeRequirementsBody, decodeSettleBody, decodeSettleResponse, detectProtocol, detectTransport, encodePayloadBody, encodePaymentPayload, encodePaymentRequired, encodeRequirementsBody, encodeSettleBody, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, s402Client, type s402ClientScheme, type s402DirectScheme, type s402Discovery, s402Error, s402ErrorCode, type s402ErrorCodeType, type s402ErrorInfo, type s402EscrowExtra, type s402EscrowPayload, type s402ExactPayload, s402Facilitator, type s402FacilitatorScheme, type s402Mandate, type s402MandateRequirements, type s402PaymentPayload, type s402PaymentPayloadBase, type s402PaymentRequirements, type s402PaymentSession, type s402PrepaidExtra, type s402PrepaidPayload, type s402RegistryQuery, s402ResourceServer, type s402RouteConfig, type s402Scheme, type s402ServerScheme, type s402ServiceEntry, type s402SettleResponse, type s402SettlementMode, type s402StreamExtra, type s402StreamPayload, type s402UnlockExtra, type s402UnlockPayload, type s402VerifyResponse, validateRequirementsShape };
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { S402_HEADERS, S402_VERSION } from "./types.mjs";
|
|
2
2
|
import { createS402Error, s402Error, s402ErrorCode } from "./errors.mjs";
|
|
3
|
-
import { decodePaymentPayload, decodePaymentRequired, decodeSettleResponse, detectProtocol, encodePaymentPayload, encodePaymentRequired, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, validateRequirementsShape } from "./http.mjs";
|
|
3
|
+
import { S402_CONTENT_TYPE, decodePayloadBody, decodePaymentPayload, decodePaymentRequired, decodeRequirementsBody, decodeSettleBody, decodeSettleResponse, detectProtocol, detectTransport, encodePayloadBody, encodePaymentPayload, encodePaymentRequired, encodeRequirementsBody, encodeSettleBody, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, validateRequirementsShape } from "./http.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/client.ts
|
|
6
6
|
var s402Client = class {
|
|
@@ -317,4 +317,4 @@ var s402Facilitator = class {
|
|
|
317
317
|
};
|
|
318
318
|
|
|
319
319
|
//#endregion
|
|
320
|
-
export { S402_HEADERS, S402_VERSION, createS402Error, decodePaymentPayload, decodePaymentRequired, decodeSettleResponse, detectProtocol, encodePaymentPayload, encodePaymentRequired, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, s402Client, s402Error, s402ErrorCode, s402Facilitator, s402ResourceServer, validateRequirementsShape };
|
|
320
|
+
export { S402_CONTENT_TYPE, S402_HEADERS, S402_VERSION, createS402Error, decodePayloadBody, decodePaymentPayload, decodePaymentRequired, decodeRequirementsBody, decodeSettleBody, decodeSettleResponse, detectProtocol, detectTransport, encodePayloadBody, encodePaymentPayload, encodePaymentRequired, encodeRequirementsBody, encodeSettleBody, encodeSettleResponse, extractRequirementsFromResponse, isValidAmount, isValidU64Amount, s402Client, s402Error, s402ErrorCode, s402Facilitator, s402ResourceServer, validateRequirementsShape };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "s402",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "s402 — Sui-native HTTP 402 wire format. Types, HTTP encoding, and scheme registry for five payment schemes. Wire-compatible with x402. Zero runtime dependencies.",
|
|
6
6
|
"license": "Apache-2.0",
|