@402flow/sdk 0.1.0-alpha.3 → 0.1.0-alpha.30
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 +123 -28
- package/dist/agent-harness.d.ts +164 -0
- package/dist/agent-harness.js +487 -0
- package/dist/agent-harness.js.map +1 -0
- package/dist/challenge-detection.d.ts +17 -5
- package/dist/challenge-detection.js +65 -102
- package/dist/challenge-detection.js.map +1 -1
- package/dist/contracts.d.ts +5939 -500
- package/dist/contracts.js +337 -20
- package/dist/contracts.js.map +1 -1
- package/dist/executors.d.ts +27 -0
- package/dist/executors.js +2 -0
- package/dist/executors.js.map +1 -0
- package/dist/harness-instructions.d.ts +15 -0
- package/dist/harness-instructions.js +28 -0
- package/dist/harness-instructions.js.map +1 -0
- package/dist/http-utils.d.ts +1 -0
- package/dist/http-utils.js +12 -0
- package/dist/http-utils.js.map +1 -0
- package/dist/index.d.ts +117 -8
- package/dist/index.js +1186 -56
- package/dist/index.js.map +1 -1
- package/dist/version.d.ts +4 -0
- package/dist/version.js +9 -0
- package/dist/version.js.map +1 -0
- package/package.json +21 -11
- package/dist/challenge-types.d.ts +0 -57
- package/dist/challenge-types.js +0 -111
- package/dist/challenge-types.js.map +0 -1
- package/dist/x402-v1.d.ts +0 -4
- package/dist/x402-v1.js +0 -53
- package/dist/x402-v1.js.map +0 -1
- package/dist/x402-v2.d.ts +0 -4
- package/dist/x402-v2.js +0 -52
- package/dist/x402-v2.js.map +0 -1
|
@@ -1,123 +1,86 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Inspect a merchant response for x402/l402 challenge evidence in either headers
|
|
3
|
+
* or a JSON body. The SDK prefers header evidence first because that is the most
|
|
4
|
+
* direct live protocol signal.
|
|
5
|
+
*/
|
|
5
6
|
export async function detectChallengeFromResponse(response) {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
const
|
|
15
|
-
if (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return undefined;
|
|
21
|
-
}
|
|
22
|
-
try {
|
|
23
|
-
const payload = await response.clone().json();
|
|
24
|
-
return parseBodyChallenge(payload);
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
return undefined;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
export function parseX402PaymentResponseFromHeaders(headers) {
|
|
31
|
-
const headerMap = headers instanceof Headers ? headers : new Headers(headers);
|
|
32
|
-
const v2Header = headerMap.get('payment-response');
|
|
33
|
-
if (v2Header) {
|
|
34
|
-
return parseX402V2PaymentResponseHeader(v2Header);
|
|
35
|
-
}
|
|
36
|
-
const v1Header = headerMap.get('x-payment-response');
|
|
37
|
-
if (v1Header) {
|
|
38
|
-
return parseX402V1PaymentResponseHeader(v1Header);
|
|
7
|
+
const headers = captureHeaders(response.headers);
|
|
8
|
+
const protocol = sniffProtocolFromHeaders(headers);
|
|
9
|
+
if (protocol) {
|
|
10
|
+
const body = await tryReadJsonBody(response);
|
|
11
|
+
return body !== undefined
|
|
12
|
+
? { protocol, headers, body }
|
|
13
|
+
: { protocol, headers };
|
|
14
|
+
}
|
|
15
|
+
const body = await tryReadJsonBody(response);
|
|
16
|
+
if (body !== undefined) {
|
|
17
|
+
const bodyProtocol = sniffProtocolFromBody(body);
|
|
18
|
+
if (bodyProtocol) {
|
|
19
|
+
return { protocol: bodyProtocol, headers, body };
|
|
20
|
+
}
|
|
39
21
|
}
|
|
40
22
|
return undefined;
|
|
41
23
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
24
|
+
function captureHeaders(source) {
|
|
25
|
+
const headers = {};
|
|
26
|
+
source.forEach((value, key) => {
|
|
27
|
+
headers[key] = value;
|
|
28
|
+
});
|
|
29
|
+
return headers;
|
|
45
30
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (attributeName && attributeValue) {
|
|
62
|
-
attributes[attributeName.toLowerCase()] = attributeValue;
|
|
31
|
+
// Header detection is the primary path because a real payable merchant usually
|
|
32
|
+
// signals the protocol directly in response headers.
|
|
33
|
+
function sniffProtocolFromHeaders(headers) {
|
|
34
|
+
if (headers['payment-required']) {
|
|
35
|
+
return 'x402';
|
|
36
|
+
}
|
|
37
|
+
const paymentProtocol = headers['x-payment-protocol']?.toLowerCase();
|
|
38
|
+
if (paymentProtocol === 'x402' || paymentProtocol === 'l402') {
|
|
39
|
+
return paymentProtocol;
|
|
40
|
+
}
|
|
41
|
+
const authenticate = headers['www-authenticate'];
|
|
42
|
+
if (authenticate) {
|
|
43
|
+
const match = authenticate.match(/\b(x402|l402)\b/i);
|
|
44
|
+
if (match) {
|
|
45
|
+
return match[1].toLowerCase();
|
|
63
46
|
}
|
|
64
|
-
match = attributePattern.exec(headerValue);
|
|
65
|
-
}
|
|
66
|
-
if (!attributes.amount || !attributes.asset) {
|
|
67
|
-
return undefined;
|
|
68
47
|
}
|
|
69
|
-
return
|
|
70
|
-
protocol,
|
|
71
|
-
money: normalizedMoneySchema.parse({
|
|
72
|
-
asset: attributes.asset,
|
|
73
|
-
amount: attributes.amount,
|
|
74
|
-
amountMinor: monetaryAmountToMinorUnits(attributes.amount, Number(attributes.precision ?? '6')),
|
|
75
|
-
precision: Number(attributes.precision ?? '6'),
|
|
76
|
-
unit: 'minor',
|
|
77
|
-
}),
|
|
78
|
-
payee: attributes.payee,
|
|
79
|
-
raw: {
|
|
80
|
-
authenticate: headerValue,
|
|
81
|
-
},
|
|
82
|
-
});
|
|
48
|
+
return undefined;
|
|
83
49
|
}
|
|
84
|
-
|
|
50
|
+
// Some compatibility merchants embed the challenge in JSON instead of, or in
|
|
51
|
+
// addition to, headers. This fallback keeps the client tolerant of that shape.
|
|
52
|
+
function sniffProtocolFromBody(payload) {
|
|
85
53
|
if (!payload || typeof payload !== 'object') {
|
|
86
54
|
return undefined;
|
|
87
55
|
}
|
|
88
|
-
const candidate = 'challenge' in payload &&
|
|
56
|
+
const candidate = 'challenge' in payload &&
|
|
57
|
+
payload.challenge &&
|
|
58
|
+
typeof payload.challenge === 'object'
|
|
89
59
|
? payload.challenge
|
|
90
60
|
: payload;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return v2Challenge;
|
|
61
|
+
if ('x402Version' in candidate) {
|
|
62
|
+
return 'x402';
|
|
94
63
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
64
|
+
if ('protocol' in candidate && typeof candidate.protocol === 'string') {
|
|
65
|
+
const protocol = candidate.protocol.toLowerCase();
|
|
66
|
+
if (protocol === 'x402' || protocol === 'l402') {
|
|
67
|
+
return protocol;
|
|
68
|
+
}
|
|
98
69
|
}
|
|
99
|
-
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
// The detector only parses JSON bodies when content-type says JSON, and it never
|
|
73
|
+
// consumes the original response stream thanks to clone().
|
|
74
|
+
async function tryReadJsonBody(response) {
|
|
75
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
76
|
+
if (!contentType.includes('application/json')) {
|
|
100
77
|
return undefined;
|
|
101
78
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const payee = 'payee' in candidate && typeof candidate.payee === 'string'
|
|
107
|
-
? candidate.payee
|
|
108
|
-
: undefined;
|
|
109
|
-
const raw = 'raw' in candidate && candidate.raw && typeof candidate.raw === 'object'
|
|
110
|
-
? candidate.raw
|
|
111
|
-
: undefined;
|
|
112
|
-
if ((protocol !== 'x402' && protocol !== 'l402') || !money) {
|
|
79
|
+
try {
|
|
80
|
+
return await response.clone().json();
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
113
83
|
return undefined;
|
|
114
84
|
}
|
|
115
|
-
return createParsedChallenge({
|
|
116
|
-
protocol,
|
|
117
|
-
money: normalizedMoneySchema.parse(money),
|
|
118
|
-
payee,
|
|
119
|
-
raw: raw ?? candidate,
|
|
120
|
-
});
|
|
121
85
|
}
|
|
122
|
-
export { getX402PaymentRequired };
|
|
123
86
|
//# sourceMappingURL=challenge-detection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"challenge-detection.js","sourceRoot":"","sources":["../src/challenge-detection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"challenge-detection.js","sourceRoot":"","sources":["../src/challenge-detection.ts"],"names":[],"mappings":"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"}
|