@peac/adapter-x402 0.10.5
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 +116 -0
- package/dist/errors.d.ts +36 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +62 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/map.d.ts +56 -0
- package/dist/map.d.ts.map +1 -0
- package/dist/map.js +111 -0
- package/dist/map.js.map +1 -0
- package/dist/types.d.ts +392 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +58 -0
- package/dist/types.js.map +1 -0
- package/dist/verify.d.ts +80 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +919 -0
- package/dist/verify.js.map +1 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# @peac/adapter-x402
|
|
2
|
+
|
|
3
|
+
x402 offer/receipt verification, term-matching, and PEAC record mapping.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package verifies x402 extension objects (offers and receipts) and maps
|
|
8
|
+
them into canonical PEAC interaction records. It implements term-matching
|
|
9
|
+
verification where `acceptIndex` is treated as an untrusted hint and the
|
|
10
|
+
binding comes from matching signed payload fields against accept terms.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add @peac/adapter-x402
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### Verify an offer against accept terms
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { verifyOffer } from '@peac/adapter-x402';
|
|
24
|
+
|
|
25
|
+
const result = verifyOffer(signedOffer, acceptEntries, acceptIndex);
|
|
26
|
+
|
|
27
|
+
if (result.valid) {
|
|
28
|
+
console.log('Matched accept entry:', result.matchedAccept);
|
|
29
|
+
console.log('Used hint:', result.usedHint);
|
|
30
|
+
} else {
|
|
31
|
+
console.log('Verification failed:', result.errors);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Select accept entry with term-matching
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { selectAccept } from '@peac/adapter-x402';
|
|
39
|
+
|
|
40
|
+
// With hint (bounds-check + term-match)
|
|
41
|
+
const match = selectAccept(offerPayload, accepts, acceptIndex);
|
|
42
|
+
|
|
43
|
+
// Without hint (scan for unique match)
|
|
44
|
+
const match = selectAccept(offerPayload, accepts);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Map to PEAC record
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { toPeacRecord } from '@peac/adapter-x402';
|
|
51
|
+
|
|
52
|
+
const record = toPeacRecord(paymentRequired, settlementResponse);
|
|
53
|
+
// record.proofs.x402.offer -- raw offer preserved for audit
|
|
54
|
+
// record.proofs.x402.receipt -- raw receipt preserved for audit
|
|
55
|
+
// record.evidence.txHash -- from signed receipt payload
|
|
56
|
+
// record.hints.acceptIndex -- { value: 0, untrusted: true }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## acceptIndex: hint-only semantics
|
|
60
|
+
|
|
61
|
+
In the x402 Offer/Receipt extension, `acceptIndex` is an unsigned envelope
|
|
62
|
+
field outside the signed payload. Verifiers MUST NOT rely on it as a binding
|
|
63
|
+
mechanism.
|
|
64
|
+
|
|
65
|
+
This package treats `acceptIndex` as advisory:
|
|
66
|
+
|
|
67
|
+
- If present: bounds-check, then term-match `accepts[acceptIndex]` against
|
|
68
|
+
the signed payload. Reject on mismatch.
|
|
69
|
+
- If absent: scan all `accepts[]` entries for a unique match. If ambiguous
|
|
70
|
+
(multiple matches), reject.
|
|
71
|
+
- If tampered: does not affect security because the binding comes from
|
|
72
|
+
comparing signed payload fields, not the unsigned index.
|
|
73
|
+
|
|
74
|
+
## API
|
|
75
|
+
|
|
76
|
+
### `verifyOffer(offer, accepts, acceptIndex?, config?)`
|
|
77
|
+
|
|
78
|
+
Verify a signed offer against accept terms. Checks structure, expiry,
|
|
79
|
+
version, signature format, and term-matching.
|
|
80
|
+
|
|
81
|
+
### `verifyReceipt(receipt, config?)`
|
|
82
|
+
|
|
83
|
+
Verify a signed receipt's structure and version.
|
|
84
|
+
|
|
85
|
+
### `matchAcceptTerms(payload, accept)`
|
|
86
|
+
|
|
87
|
+
Compare offer payload fields against a single accept entry. Returns an
|
|
88
|
+
array of mismatched field names (empty means match).
|
|
89
|
+
|
|
90
|
+
### `selectAccept(payload, accepts, acceptIndex?)`
|
|
91
|
+
|
|
92
|
+
Select the matching accept entry. Throws `X402Error` on failure.
|
|
93
|
+
|
|
94
|
+
### `toPeacRecord(paymentRequired, settlementResponse)`
|
|
95
|
+
|
|
96
|
+
Map an x402 payment flow to a PEAC interaction record.
|
|
97
|
+
|
|
98
|
+
## Error handling
|
|
99
|
+
|
|
100
|
+
All verification functions return structured results with error arrays.
|
|
101
|
+
The `selectAccept` and `toPeacRecord` functions throw `X402Error` with:
|
|
102
|
+
|
|
103
|
+
- `code`: Machine-readable error code (lowercase snake_case)
|
|
104
|
+
- `httpStatus`: Suggested HTTP status code
|
|
105
|
+
- `field`: Optional field that caused the error
|
|
106
|
+
- `details`: Optional structured details
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
Apache-2.0
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
PEAC Protocol is an open source project stewarded by Originary and community contributors.
|
|
115
|
+
|
|
116
|
+
[Docs](https://www.peacprotocol.org) | [GitHub](https://github.com/peacprotocol/peac) | [Originary](https://www.originary.xyz)
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 adapter error codes and error class
|
|
3
|
+
*
|
|
4
|
+
* Error codes follow PEAC adapter convention: lowercase snake_case.
|
|
5
|
+
* These are adapter-level errors; kernel-level errors use E_* prefix.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* x402 adapter error codes
|
|
9
|
+
*
|
|
10
|
+
* Categories:
|
|
11
|
+
* - offer_*: Offer validation/verification errors
|
|
12
|
+
* - receipt_*: Receipt validation/verification errors
|
|
13
|
+
* - accept_*: Accept selection/matching errors
|
|
14
|
+
* - payload_*: Generic payload errors
|
|
15
|
+
* - amount_*: Amount validation errors
|
|
16
|
+
* - network_*: Network validation errors
|
|
17
|
+
*/
|
|
18
|
+
export type X402ErrorCode = 'offer_invalid_format' | 'offer_expired' | 'offer_version_unsupported' | 'offer_signature_invalid' | 'receipt_invalid_format' | 'receipt_signature_invalid' | 'receipt_version_unsupported' | 'accept_index_out_of_range' | 'accept_no_match' | 'accept_ambiguous' | 'accept_term_mismatch' | 'accept_too_many_entries' | 'payload_missing_field' | 'payload_tampered' | 'amount_invalid' | 'network_invalid';
|
|
19
|
+
/**
|
|
20
|
+
* Custom error class for x402 adapter operations
|
|
21
|
+
*
|
|
22
|
+
* Provides structured error information with code, HTTP status,
|
|
23
|
+
* and optional field/details for debugging.
|
|
24
|
+
*/
|
|
25
|
+
export declare class X402Error extends Error {
|
|
26
|
+
readonly code: X402ErrorCode;
|
|
27
|
+
readonly httpStatus: number;
|
|
28
|
+
readonly field?: string;
|
|
29
|
+
readonly details?: Record<string, unknown>;
|
|
30
|
+
constructor(code: X402ErrorCode, message: string, options?: {
|
|
31
|
+
field?: string;
|
|
32
|
+
details?: Record<string, unknown>;
|
|
33
|
+
});
|
|
34
|
+
toJSON(): Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,GACrB,sBAAsB,GACtB,eAAe,GACf,2BAA2B,GAC3B,yBAAyB,GACzB,wBAAwB,GACxB,2BAA2B,GAC3B,6BAA6B,GAC7B,2BAA2B,GAC3B,iBAAiB,GACjB,kBAAkB,GAClB,sBAAsB,GACtB,yBAAyB,GACzB,uBAAuB,GACvB,kBAAkB,GAClB,gBAAgB,GAChB,iBAAiB,CAAC;AAwBtB;;;;;GAKG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAGzC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE;IAUjE,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAUlC"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* x402 adapter error codes and error class
|
|
4
|
+
*
|
|
5
|
+
* Error codes follow PEAC adapter convention: lowercase snake_case.
|
|
6
|
+
* These are adapter-level errors; kernel-level errors use E_* prefix.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.X402Error = void 0;
|
|
10
|
+
/**
|
|
11
|
+
* HTTP status mapping for error codes
|
|
12
|
+
*/
|
|
13
|
+
const ERROR_HTTP_STATUS = {
|
|
14
|
+
offer_invalid_format: 400,
|
|
15
|
+
offer_expired: 400,
|
|
16
|
+
offer_version_unsupported: 400,
|
|
17
|
+
offer_signature_invalid: 401,
|
|
18
|
+
receipt_invalid_format: 400,
|
|
19
|
+
receipt_signature_invalid: 401,
|
|
20
|
+
receipt_version_unsupported: 400,
|
|
21
|
+
accept_index_out_of_range: 400,
|
|
22
|
+
accept_no_match: 400,
|
|
23
|
+
accept_ambiguous: 400,
|
|
24
|
+
accept_term_mismatch: 400,
|
|
25
|
+
accept_too_many_entries: 400,
|
|
26
|
+
payload_missing_field: 400,
|
|
27
|
+
payload_tampered: 401,
|
|
28
|
+
amount_invalid: 400,
|
|
29
|
+
network_invalid: 400,
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Custom error class for x402 adapter operations
|
|
33
|
+
*
|
|
34
|
+
* Provides structured error information with code, HTTP status,
|
|
35
|
+
* and optional field/details for debugging.
|
|
36
|
+
*/
|
|
37
|
+
class X402Error extends Error {
|
|
38
|
+
code;
|
|
39
|
+
httpStatus;
|
|
40
|
+
field;
|
|
41
|
+
details;
|
|
42
|
+
constructor(code, message, options) {
|
|
43
|
+
super(message);
|
|
44
|
+
this.name = 'X402Error';
|
|
45
|
+
this.code = code;
|
|
46
|
+
this.httpStatus = ERROR_HTTP_STATUS[code] ?? 400;
|
|
47
|
+
this.field = options?.field;
|
|
48
|
+
this.details = options?.details;
|
|
49
|
+
}
|
|
50
|
+
toJSON() {
|
|
51
|
+
return {
|
|
52
|
+
name: this.name,
|
|
53
|
+
code: this.code,
|
|
54
|
+
message: this.message,
|
|
55
|
+
httpStatus: this.httpStatus,
|
|
56
|
+
...(this.field !== undefined && { field: this.field }),
|
|
57
|
+
...(this.details !== undefined && { details: this.details }),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.X402Error = X402Error;
|
|
62
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AA+BH;;GAEG;AACH,MAAM,iBAAiB,GAAkC;IACvD,oBAAoB,EAAE,GAAG;IACzB,aAAa,EAAE,GAAG;IAClB,yBAAyB,EAAE,GAAG;IAC9B,uBAAuB,EAAE,GAAG;IAC5B,sBAAsB,EAAE,GAAG;IAC3B,yBAAyB,EAAE,GAAG;IAC9B,2BAA2B,EAAE,GAAG;IAChC,yBAAyB,EAAE,GAAG;IAC9B,eAAe,EAAE,GAAG;IACpB,gBAAgB,EAAE,GAAG;IACrB,oBAAoB,EAAE,GAAG;IACzB,uBAAuB,EAAE,GAAG;IAC5B,qBAAqB,EAAE,GAAG;IAC1B,gBAAgB,EAAE,GAAG;IACrB,cAAc,EAAE,GAAG;IACnB,eAAe,EAAE,GAAG;CACrB,CAAC;AAEF;;;;;GAKG;AACH,MAAa,SAAU,SAAQ,KAAK;IACzB,IAAI,CAAgB;IACpB,UAAU,CAAS;IACnB,KAAK,CAAU;IACf,OAAO,CAA2B;IAE3C,YACE,IAAmB,EACnB,OAAe,EACf,OAA+D;QAE/D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;QACjD,IAAI,CAAC,KAAK,GAAG,OAAO,EAAE,KAAK,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;IAClC,CAAC;IAED,MAAM;QACJ,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,GAAG,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YACtD,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;SAC7D,CAAC;IACJ,CAAC;CACF;AA7BD,8BA6BC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @peac/adapter-x402
|
|
3
|
+
*
|
|
4
|
+
* x402 Offer/Receipt extension verification, term-matching, and PEAC record mapping.
|
|
5
|
+
*
|
|
6
|
+
* NOTE: This adapter targets the x402 Offer/Receipt EXTENSION,
|
|
7
|
+
* NOT the baseline x402 header flow. The profile identifier reflects this:
|
|
8
|
+
* `peac-x402-offer-receipt/0.1` (extension) vs `peac-x402/0.1` (baseline, reserved).
|
|
9
|
+
*
|
|
10
|
+
* Key capabilities:
|
|
11
|
+
* - Structural validation of x402 offers and receipts
|
|
12
|
+
* - Term-matching: verify signed payload against accept entries
|
|
13
|
+
* - Accept selection with acceptIndex as untrusted hint
|
|
14
|
+
* - Mapping to canonical PEAC interaction records
|
|
15
|
+
* - DoS protection: limits on accepts array size
|
|
16
|
+
* - Amount/network validation: CAIP-2 format, integer strings
|
|
17
|
+
*
|
|
18
|
+
* IMPORTANT: This package does NOT perform cryptographic signature verification
|
|
19
|
+
* (EIP-712 recovery, JWS validation). That is the caller's responsibility.
|
|
20
|
+
* `valid: true` does NOT imply cryptographic signature validity unless
|
|
21
|
+
* a CryptoVerifier is supplied and `verification.cryptographic.verified` is true.
|
|
22
|
+
*
|
|
23
|
+
* The focus is on term-matching and record mapping -- the verification
|
|
24
|
+
* layer that makes unsigned acceptIndex irrelevant for security.
|
|
25
|
+
*
|
|
26
|
+
* @packageDocumentation
|
|
27
|
+
*/
|
|
28
|
+
export type { SignatureFormat, OfferPayload, SignedOffer, ReceiptPayload, SignedReceipt, AcceptEntry, X402PaymentRequired, X402SettlementResponse, OfferVerification, ReceiptVerification, VerificationError, VerificationStatus, X402PeacRecord, X402AdapterConfig, MismatchPolicy, } from './types.js';
|
|
29
|
+
export { X402_OFFER_RECEIPT_PROFILE, MAX_ACCEPT_ENTRIES, MAX_TOTAL_ACCEPTS_BYTES, MAX_AMOUNT_LENGTH, } from './types.js';
|
|
30
|
+
export type { Result, AdapterError, AdapterErrorCode, JsonObject } from './types.js';
|
|
31
|
+
export { X402Error } from './errors.js';
|
|
32
|
+
export type { X402ErrorCode } from './errors.js';
|
|
33
|
+
export { verifyOffer, verifyReceipt, matchAcceptTerms, selectAccept } from './verify.js';
|
|
34
|
+
export { toPeacRecord } from './map.js';
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,YAAY,EACV,eAAe,EACf,YAAY,EACZ,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,cAAc,GACf,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,0BAA0B,EAC1B,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGrF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGzF,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @peac/adapter-x402
|
|
4
|
+
*
|
|
5
|
+
* x402 Offer/Receipt extension verification, term-matching, and PEAC record mapping.
|
|
6
|
+
*
|
|
7
|
+
* NOTE: This adapter targets the x402 Offer/Receipt EXTENSION,
|
|
8
|
+
* NOT the baseline x402 header flow. The profile identifier reflects this:
|
|
9
|
+
* `peac-x402-offer-receipt/0.1` (extension) vs `peac-x402/0.1` (baseline, reserved).
|
|
10
|
+
*
|
|
11
|
+
* Key capabilities:
|
|
12
|
+
* - Structural validation of x402 offers and receipts
|
|
13
|
+
* - Term-matching: verify signed payload against accept entries
|
|
14
|
+
* - Accept selection with acceptIndex as untrusted hint
|
|
15
|
+
* - Mapping to canonical PEAC interaction records
|
|
16
|
+
* - DoS protection: limits on accepts array size
|
|
17
|
+
* - Amount/network validation: CAIP-2 format, integer strings
|
|
18
|
+
*
|
|
19
|
+
* IMPORTANT: This package does NOT perform cryptographic signature verification
|
|
20
|
+
* (EIP-712 recovery, JWS validation). That is the caller's responsibility.
|
|
21
|
+
* `valid: true` does NOT imply cryptographic signature validity unless
|
|
22
|
+
* a CryptoVerifier is supplied and `verification.cryptographic.verified` is true.
|
|
23
|
+
*
|
|
24
|
+
* The focus is on term-matching and record mapping -- the verification
|
|
25
|
+
* layer that makes unsigned acceptIndex irrelevant for security.
|
|
26
|
+
*
|
|
27
|
+
* @packageDocumentation
|
|
28
|
+
*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.toPeacRecord = exports.selectAccept = exports.matchAcceptTerms = exports.verifyReceipt = exports.verifyOffer = exports.X402Error = exports.MAX_AMOUNT_LENGTH = exports.MAX_TOTAL_ACCEPTS_BYTES = exports.MAX_ACCEPT_ENTRIES = exports.X402_OFFER_RECEIPT_PROFILE = void 0;
|
|
31
|
+
// Constants
|
|
32
|
+
var types_js_1 = require("./types.js");
|
|
33
|
+
Object.defineProperty(exports, "X402_OFFER_RECEIPT_PROFILE", { enumerable: true, get: function () { return types_js_1.X402_OFFER_RECEIPT_PROFILE; } });
|
|
34
|
+
Object.defineProperty(exports, "MAX_ACCEPT_ENTRIES", { enumerable: true, get: function () { return types_js_1.MAX_ACCEPT_ENTRIES; } });
|
|
35
|
+
Object.defineProperty(exports, "MAX_TOTAL_ACCEPTS_BYTES", { enumerable: true, get: function () { return types_js_1.MAX_TOTAL_ACCEPTS_BYTES; } });
|
|
36
|
+
Object.defineProperty(exports, "MAX_AMOUNT_LENGTH", { enumerable: true, get: function () { return types_js_1.MAX_AMOUNT_LENGTH; } });
|
|
37
|
+
// Errors
|
|
38
|
+
var errors_js_1 = require("./errors.js");
|
|
39
|
+
Object.defineProperty(exports, "X402Error", { enumerable: true, get: function () { return errors_js_1.X402Error; } });
|
|
40
|
+
// Verification
|
|
41
|
+
var verify_js_1 = require("./verify.js");
|
|
42
|
+
Object.defineProperty(exports, "verifyOffer", { enumerable: true, get: function () { return verify_js_1.verifyOffer; } });
|
|
43
|
+
Object.defineProperty(exports, "verifyReceipt", { enumerable: true, get: function () { return verify_js_1.verifyReceipt; } });
|
|
44
|
+
Object.defineProperty(exports, "matchAcceptTerms", { enumerable: true, get: function () { return verify_js_1.matchAcceptTerms; } });
|
|
45
|
+
Object.defineProperty(exports, "selectAccept", { enumerable: true, get: function () { return verify_js_1.selectAccept; } });
|
|
46
|
+
// Mapping
|
|
47
|
+
var map_js_1 = require("./map.js");
|
|
48
|
+
Object.defineProperty(exports, "toPeacRecord", { enumerable: true, get: function () { return map_js_1.toPeacRecord; } });
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;;;AAqBH,YAAY;AACZ,uCAKoB;AAJlB,sHAAA,0BAA0B,OAAA;AAC1B,8GAAA,kBAAkB,OAAA;AAClB,mHAAA,uBAAuB,OAAA;AACvB,6GAAA,iBAAiB,OAAA;AAMnB,SAAS;AACT,yCAAwC;AAA/B,sGAAA,SAAS,OAAA;AAGlB,eAAe;AACf,yCAAyF;AAAhF,wGAAA,WAAW,OAAA;AAAE,0GAAA,aAAa,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AAAE,yGAAA,YAAY,OAAA;AAEnE,UAAU;AACV,mCAAwC;AAA/B,sGAAA,YAAY,OAAA"}
|
package/dist/map.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 to PEAC record mapping
|
|
3
|
+
*
|
|
4
|
+
* Maps x402 PaymentRequired + SettlementResponse into a canonical
|
|
5
|
+
* PEAC interaction record (X402PeacRecord).
|
|
6
|
+
*
|
|
7
|
+
* NOTE: This mapper produces records for the x402 Offer/Receipt EXTENSION,
|
|
8
|
+
* NOT the baseline x402 header flow. The profile identifier reflects this.
|
|
9
|
+
*
|
|
10
|
+
* The record preserves:
|
|
11
|
+
* - Raw proofs (offer + receipt) for audit/dispute
|
|
12
|
+
* - Normalized evidence fields from signed payloads
|
|
13
|
+
* - Unsigned hints (acceptIndex) explicitly marked as untrusted
|
|
14
|
+
* - Verification status metadata (structural, cryptographic, termMatching)
|
|
15
|
+
*/
|
|
16
|
+
import type { X402PaymentRequired, X402SettlementResponse, X402PeacRecord, OfferVerification } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Options for record mapping
|
|
19
|
+
*/
|
|
20
|
+
export interface ToPeacRecordOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Offer verification result (to populate verification hints)
|
|
23
|
+
*
|
|
24
|
+
* The termMatching field in OfferVerification is used to derive
|
|
25
|
+
* hints.acceptIndex.mismatchDetected automatically. This makes
|
|
26
|
+
* mismatch detection first-class without requiring external options.
|
|
27
|
+
*/
|
|
28
|
+
offerVerification?: OfferVerification;
|
|
29
|
+
/**
|
|
30
|
+
* Whether cryptographic signature verification was performed
|
|
31
|
+
* Default: false (adapter does NOT perform crypto verification)
|
|
32
|
+
*/
|
|
33
|
+
cryptoVerified?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Signer identity (if crypto verification was performed)
|
|
36
|
+
*/
|
|
37
|
+
cryptoSigner?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Map x402 payment flow to a PEAC interaction record
|
|
41
|
+
*
|
|
42
|
+
* Takes a PaymentRequired (offer side) and SettlementResponse (receipt side)
|
|
43
|
+
* and produces a canonical PEAC record with normalized evidence.
|
|
44
|
+
*
|
|
45
|
+
* IMPORTANT: The resulting record does NOT indicate cryptographic signature
|
|
46
|
+
* validity unless you explicitly pass `cryptoVerified: true` in options.
|
|
47
|
+
* See `hints.verification.cryptographic` in the output.
|
|
48
|
+
*
|
|
49
|
+
* @param paymentRequired - The 402 response with offer and accepts
|
|
50
|
+
* @param settlementResponse - The settlement response with receipt
|
|
51
|
+
* @param options - Optional mapping options
|
|
52
|
+
* @returns Canonical PEAC interaction record
|
|
53
|
+
* @throws X402Error if inputs are structurally invalid
|
|
54
|
+
*/
|
|
55
|
+
export declare function toPeacRecord(paymentRequired: X402PaymentRequired, settlementResponse: X402SettlementResponse, options?: ToPeacRecordOptions): X402PeacRecord;
|
|
56
|
+
//# sourceMappingURL=map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EACV,mBAAmB,EACnB,sBAAsB,EACtB,cAAc,EAEd,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAGpB;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,eAAe,EAAE,mBAAmB,EACpC,kBAAkB,EAAE,sBAAsB,EAC1C,OAAO,CAAC,EAAE,mBAAmB,GAC5B,cAAc,CAyFhB"}
|
package/dist/map.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* x402 to PEAC record mapping
|
|
4
|
+
*
|
|
5
|
+
* Maps x402 PaymentRequired + SettlementResponse into a canonical
|
|
6
|
+
* PEAC interaction record (X402PeacRecord).
|
|
7
|
+
*
|
|
8
|
+
* NOTE: This mapper produces records for the x402 Offer/Receipt EXTENSION,
|
|
9
|
+
* NOT the baseline x402 header flow. The profile identifier reflects this.
|
|
10
|
+
*
|
|
11
|
+
* The record preserves:
|
|
12
|
+
* - Raw proofs (offer + receipt) for audit/dispute
|
|
13
|
+
* - Normalized evidence fields from signed payloads
|
|
14
|
+
* - Unsigned hints (acceptIndex) explicitly marked as untrusted
|
|
15
|
+
* - Verification status metadata (structural, cryptographic, termMatching)
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.toPeacRecord = toPeacRecord;
|
|
19
|
+
const errors_js_1 = require("./errors.js");
|
|
20
|
+
const types_js_1 = require("./types.js");
|
|
21
|
+
/**
|
|
22
|
+
* Map x402 payment flow to a PEAC interaction record
|
|
23
|
+
*
|
|
24
|
+
* Takes a PaymentRequired (offer side) and SettlementResponse (receipt side)
|
|
25
|
+
* and produces a canonical PEAC record with normalized evidence.
|
|
26
|
+
*
|
|
27
|
+
* IMPORTANT: The resulting record does NOT indicate cryptographic signature
|
|
28
|
+
* validity unless you explicitly pass `cryptoVerified: true` in options.
|
|
29
|
+
* See `hints.verification.cryptographic` in the output.
|
|
30
|
+
*
|
|
31
|
+
* @param paymentRequired - The 402 response with offer and accepts
|
|
32
|
+
* @param settlementResponse - The settlement response with receipt
|
|
33
|
+
* @param options - Optional mapping options
|
|
34
|
+
* @returns Canonical PEAC interaction record
|
|
35
|
+
* @throws X402Error if inputs are structurally invalid
|
|
36
|
+
*/
|
|
37
|
+
function toPeacRecord(paymentRequired, settlementResponse, options) {
|
|
38
|
+
const offer = paymentRequired.offer;
|
|
39
|
+
const receipt = settlementResponse.receipt;
|
|
40
|
+
if (!offer?.payload) {
|
|
41
|
+
throw new errors_js_1.X402Error('offer_invalid_format', 'PaymentRequired must contain a valid offer with payload');
|
|
42
|
+
}
|
|
43
|
+
if (!receipt?.payload) {
|
|
44
|
+
throw new errors_js_1.X402Error('receipt_invalid_format', 'SettlementResponse must contain a valid receipt with payload');
|
|
45
|
+
}
|
|
46
|
+
const offerPayload = offer.payload;
|
|
47
|
+
const receiptPayload = receipt.payload;
|
|
48
|
+
// Build hints (unsigned metadata, explicitly untrusted)
|
|
49
|
+
const hints = {};
|
|
50
|
+
// Derive mismatchDetected from termMatching (first-class, always boolean when present)
|
|
51
|
+
const termMatching = options?.offerVerification?.termMatching;
|
|
52
|
+
const mismatchDetected = termMatching?.hintMismatchDetected ?? false;
|
|
53
|
+
if (paymentRequired.acceptIndex !== undefined) {
|
|
54
|
+
hints.acceptIndex = {
|
|
55
|
+
value: paymentRequired.acceptIndex,
|
|
56
|
+
untrusted: true,
|
|
57
|
+
...(mismatchDetected && { mismatchDetected: true }),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const resourceUrl = paymentRequired.resourceUrl ?? settlementResponse.resourceUrl;
|
|
61
|
+
if (resourceUrl) {
|
|
62
|
+
hints.resourceUrl = resourceUrl;
|
|
63
|
+
}
|
|
64
|
+
// Build verification status
|
|
65
|
+
// IMPORTANT: If offerVerification is not provided, we cannot assume terms matched.
|
|
66
|
+
// Callers SHOULD provide offerVerification for a complete record.
|
|
67
|
+
const offerVerification = options?.offerVerification;
|
|
68
|
+
const termMatchingVerified = offerVerification !== undefined;
|
|
69
|
+
const verification = {
|
|
70
|
+
structural: true,
|
|
71
|
+
cryptographic: {
|
|
72
|
+
verified: options?.cryptoVerified ?? false,
|
|
73
|
+
...(!(options?.cryptoVerified ?? false) && { reason: 'not_checked' }),
|
|
74
|
+
format: offer.format,
|
|
75
|
+
...(options?.cryptoSigner && { signer: options.cryptoSigner }),
|
|
76
|
+
},
|
|
77
|
+
termMatching: {
|
|
78
|
+
// Safe-by-default: if verification wasn't performed, indicate that clearly
|
|
79
|
+
matched: termMatchingVerified ? offerVerification.valid : false,
|
|
80
|
+
method: offerVerification?.usedHint ? 'hint' : 'scan',
|
|
81
|
+
...(offerVerification?.matchedIndex !== undefined && {
|
|
82
|
+
matchedIndex: offerVerification.matchedIndex,
|
|
83
|
+
}),
|
|
84
|
+
// Add flag to indicate if term-matching was actually performed
|
|
85
|
+
...(!termMatchingVerified && { reason: 'not_verified' }),
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
hints.verification = verification;
|
|
89
|
+
return {
|
|
90
|
+
version: types_js_1.X402_OFFER_RECEIPT_PROFILE,
|
|
91
|
+
proofs: {
|
|
92
|
+
x402: {
|
|
93
|
+
offer,
|
|
94
|
+
receipt,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
evidence: {
|
|
98
|
+
validUntil: offerPayload.validUntil,
|
|
99
|
+
network: offerPayload.network,
|
|
100
|
+
payee: offerPayload.payTo,
|
|
101
|
+
asset: offerPayload.asset,
|
|
102
|
+
amount: offerPayload.amount,
|
|
103
|
+
txHash: receiptPayload.txHash,
|
|
104
|
+
offerVersion: offerPayload.version,
|
|
105
|
+
...(receiptPayload.version && { receiptVersion: receiptPayload.version }),
|
|
106
|
+
},
|
|
107
|
+
hints,
|
|
108
|
+
createdAt: new Date().toISOString(),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=map.js.map
|
package/dist/map.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map.js","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"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"}
|