@atxp/mpp 0.10.7

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 ADDED
@@ -0,0 +1,119 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * MPP (Machine Payments Protocol) challenge parsing.
5
+ *
6
+ * MPP challenges come in two forms:
7
+ * 1. HTTP level: HTTP 402 with WWW-Authenticate: Payment header
8
+ * 2. MCP level: JSON-RPC error with code -32042 containing MPP data
9
+ */
10
+ const MPP_ERROR_CODE = -32042;
11
+ const REQUIRED_FIELDS = [
12
+ 'id', 'method', 'intent', 'amount', 'currency', 'network', 'recipient'
13
+ ];
14
+ /**
15
+ * Parse MPP challenge from WWW-Authenticate header.
16
+ * Format: Payment method="tempo", intent="charge", id="ch_xxx", ...
17
+ */
18
+ function parseMPPHeader(headerValue) {
19
+ if (!headerValue || !headerValue.startsWith('Payment')) {
20
+ return null;
21
+ }
22
+ // Strip leading "Payment" keyword
23
+ const paramString = headerValue.slice('Payment'.length).trim();
24
+ if (!paramString) {
25
+ return null;
26
+ }
27
+ // Parse key="value" pairs
28
+ const params = {};
29
+ const regex = /(\w+)="([^"]*)"/g;
30
+ let match;
31
+ while ((match = regex.exec(paramString)) !== null) {
32
+ params[match[1]] = match[2];
33
+ }
34
+ // Validate all required fields are present
35
+ for (const field of REQUIRED_FIELDS) {
36
+ if (!params[field]) {
37
+ return null;
38
+ }
39
+ }
40
+ return {
41
+ id: params.id,
42
+ method: params.method,
43
+ intent: params.intent,
44
+ amount: params.amount,
45
+ currency: params.currency,
46
+ network: params.network,
47
+ recipient: params.recipient,
48
+ };
49
+ }
50
+ /**
51
+ * Parse MPP challenge from MCP JSON-RPC error data.
52
+ */
53
+ function parseMPPFromMCPError(errorData) {
54
+ if (typeof errorData !== 'object' || errorData === null) {
55
+ return null;
56
+ }
57
+ const data = errorData;
58
+ const mpp = data.mpp;
59
+ if (typeof mpp !== 'object' || mpp === null) {
60
+ return null;
61
+ }
62
+ const mppObj = mpp;
63
+ // Validate all required fields
64
+ for (const field of REQUIRED_FIELDS) {
65
+ if (typeof mppObj[field] !== 'string') {
66
+ return null;
67
+ }
68
+ }
69
+ return {
70
+ id: mppObj.id,
71
+ method: mppObj.method,
72
+ intent: mppObj.intent,
73
+ amount: mppObj.amount,
74
+ currency: mppObj.currency,
75
+ network: mppObj.network,
76
+ recipient: mppObj.recipient,
77
+ };
78
+ }
79
+ /**
80
+ * Check if a Response has an MPP challenge (via WWW-Authenticate header).
81
+ */
82
+ function hasMPPChallenge(response) {
83
+ const header = response.headers.get('WWW-Authenticate');
84
+ if (!header)
85
+ return false;
86
+ return header.startsWith('Payment');
87
+ }
88
+ /**
89
+ * Check if a Response body contains an MCP error with MPP data.
90
+ * Clones the response so the original body is not consumed.
91
+ */
92
+ async function hasMPPMCPError(response) {
93
+ try {
94
+ const cloned = response.clone();
95
+ const body = await cloned.text();
96
+ if (!body)
97
+ return false;
98
+ const parsed = JSON.parse(body);
99
+ if (typeof parsed === 'object' &&
100
+ parsed !== null &&
101
+ typeof parsed.error === 'object' &&
102
+ parsed.error !== null &&
103
+ parsed.error.code === MPP_ERROR_CODE) {
104
+ const challenge = parseMPPFromMCPError(parsed.error.data);
105
+ return challenge !== null;
106
+ }
107
+ return false;
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+
114
+ exports.MPP_ERROR_CODE = MPP_ERROR_CODE;
115
+ exports.hasMPPChallenge = hasMPPChallenge;
116
+ exports.hasMPPMCPError = hasMPPMCPError;
117
+ exports.parseMPPFromMCPError = parseMPPFromMCPError;
118
+ exports.parseMPPHeader = parseMPPHeader;
119
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/mppChallenge.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * MPP (Machine Payments Protocol) challenge parsing.
3
+ *
4
+ * MPP challenges come in two forms:
5
+ * 1. HTTP level: HTTP 402 with WWW-Authenticate: Payment header
6
+ * 2. MCP level: JSON-RPC error with code -32042 containing MPP data
7
+ */
8
+ declare const MPP_ERROR_CODE = -32042;
9
+ interface MPPChallenge {
10
+ id: string;
11
+ method: string;
12
+ intent: string;
13
+ amount: string;
14
+ currency: string;
15
+ network: string;
16
+ recipient: string;
17
+ }
18
+ /**
19
+ * Parse MPP challenge from WWW-Authenticate header.
20
+ * Format: Payment method="tempo", intent="charge", id="ch_xxx", ...
21
+ */
22
+ declare function parseMPPHeader(headerValue: string): MPPChallenge | null;
23
+ /**
24
+ * Parse MPP challenge from MCP JSON-RPC error data.
25
+ */
26
+ declare function parseMPPFromMCPError(errorData: unknown): MPPChallenge | null;
27
+ /**
28
+ * Check if a Response has an MPP challenge (via WWW-Authenticate header).
29
+ */
30
+ declare function hasMPPChallenge(response: Response): boolean;
31
+ /**
32
+ * Check if a Response body contains an MCP error with MPP data.
33
+ * Clones the response so the original body is not consumed.
34
+ */
35
+ declare function hasMPPMCPError(response: Response): Promise<boolean>;
36
+
37
+ export { MPP_ERROR_CODE, hasMPPChallenge, hasMPPMCPError, parseMPPFromMCPError, parseMPPHeader };
38
+ export type { MPPChallenge };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,KAAK,YAAY,EACjB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,cAAc,GACf,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,113 @@
1
+ /**
2
+ * MPP (Machine Payments Protocol) challenge parsing.
3
+ *
4
+ * MPP challenges come in two forms:
5
+ * 1. HTTP level: HTTP 402 with WWW-Authenticate: Payment header
6
+ * 2. MCP level: JSON-RPC error with code -32042 containing MPP data
7
+ */
8
+ const MPP_ERROR_CODE = -32042;
9
+ const REQUIRED_FIELDS = [
10
+ 'id', 'method', 'intent', 'amount', 'currency', 'network', 'recipient'
11
+ ];
12
+ /**
13
+ * Parse MPP challenge from WWW-Authenticate header.
14
+ * Format: Payment method="tempo", intent="charge", id="ch_xxx", ...
15
+ */
16
+ function parseMPPHeader(headerValue) {
17
+ if (!headerValue || !headerValue.startsWith('Payment')) {
18
+ return null;
19
+ }
20
+ // Strip leading "Payment" keyword
21
+ const paramString = headerValue.slice('Payment'.length).trim();
22
+ if (!paramString) {
23
+ return null;
24
+ }
25
+ // Parse key="value" pairs
26
+ const params = {};
27
+ const regex = /(\w+)="([^"]*)"/g;
28
+ let match;
29
+ while ((match = regex.exec(paramString)) !== null) {
30
+ params[match[1]] = match[2];
31
+ }
32
+ // Validate all required fields are present
33
+ for (const field of REQUIRED_FIELDS) {
34
+ if (!params[field]) {
35
+ return null;
36
+ }
37
+ }
38
+ return {
39
+ id: params.id,
40
+ method: params.method,
41
+ intent: params.intent,
42
+ amount: params.amount,
43
+ currency: params.currency,
44
+ network: params.network,
45
+ recipient: params.recipient,
46
+ };
47
+ }
48
+ /**
49
+ * Parse MPP challenge from MCP JSON-RPC error data.
50
+ */
51
+ function parseMPPFromMCPError(errorData) {
52
+ if (typeof errorData !== 'object' || errorData === null) {
53
+ return null;
54
+ }
55
+ const data = errorData;
56
+ const mpp = data.mpp;
57
+ if (typeof mpp !== 'object' || mpp === null) {
58
+ return null;
59
+ }
60
+ const mppObj = mpp;
61
+ // Validate all required fields
62
+ for (const field of REQUIRED_FIELDS) {
63
+ if (typeof mppObj[field] !== 'string') {
64
+ return null;
65
+ }
66
+ }
67
+ return {
68
+ id: mppObj.id,
69
+ method: mppObj.method,
70
+ intent: mppObj.intent,
71
+ amount: mppObj.amount,
72
+ currency: mppObj.currency,
73
+ network: mppObj.network,
74
+ recipient: mppObj.recipient,
75
+ };
76
+ }
77
+ /**
78
+ * Check if a Response has an MPP challenge (via WWW-Authenticate header).
79
+ */
80
+ function hasMPPChallenge(response) {
81
+ const header = response.headers.get('WWW-Authenticate');
82
+ if (!header)
83
+ return false;
84
+ return header.startsWith('Payment');
85
+ }
86
+ /**
87
+ * Check if a Response body contains an MCP error with MPP data.
88
+ * Clones the response so the original body is not consumed.
89
+ */
90
+ async function hasMPPMCPError(response) {
91
+ try {
92
+ const cloned = response.clone();
93
+ const body = await cloned.text();
94
+ if (!body)
95
+ return false;
96
+ const parsed = JSON.parse(body);
97
+ if (typeof parsed === 'object' &&
98
+ parsed !== null &&
99
+ typeof parsed.error === 'object' &&
100
+ parsed.error !== null &&
101
+ parsed.error.code === MPP_ERROR_CODE) {
102
+ const challenge = parseMPPFromMCPError(parsed.error.data);
103
+ return challenge !== null;
104
+ }
105
+ return false;
106
+ }
107
+ catch {
108
+ return false;
109
+ }
110
+ }
111
+
112
+ export { MPP_ERROR_CODE, hasMPPChallenge, hasMPPMCPError, parseMPPFromMCPError, parseMPPHeader };
113
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/mppChallenge.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * MPP (Machine Payments Protocol) challenge parsing.
3
+ *
4
+ * MPP challenges come in two forms:
5
+ * 1. HTTP level: HTTP 402 with WWW-Authenticate: Payment header
6
+ * 2. MCP level: JSON-RPC error with code -32042 containing MPP data
7
+ */
8
+ export declare const MPP_ERROR_CODE = -32042;
9
+ export interface MPPChallenge {
10
+ id: string;
11
+ method: string;
12
+ intent: string;
13
+ amount: string;
14
+ currency: string;
15
+ network: string;
16
+ recipient: string;
17
+ }
18
+ /**
19
+ * Parse MPP challenge from WWW-Authenticate header.
20
+ * Format: Payment method="tempo", intent="charge", id="ch_xxx", ...
21
+ */
22
+ export declare function parseMPPHeader(headerValue: string): MPPChallenge | null;
23
+ /**
24
+ * Parse MPP challenge from MCP JSON-RPC error data.
25
+ */
26
+ export declare function parseMPPFromMCPError(errorData: unknown): MPPChallenge | null;
27
+ /**
28
+ * Check if a Response has an MPP challenge (via WWW-Authenticate header).
29
+ */
30
+ export declare function hasMPPChallenge(response: Response): boolean;
31
+ /**
32
+ * Check if a Response body contains an MCP error with MPP data.
33
+ * Clones the response so the original body is not consumed.
34
+ */
35
+ export declare function hasMPPMCPError(response: Response): Promise<boolean>;
36
+ //# sourceMappingURL=mppChallenge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mppChallenge.d.ts","sourceRoot":"","sources":["../src/mppChallenge.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,cAAc,SAAS,CAAC;AAErC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAmCvE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CA8B5E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAI3D;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAuBzE"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * MPP (Machine Payments Protocol) challenge parsing.
3
+ *
4
+ * MPP challenges come in two forms:
5
+ * 1. HTTP level: HTTP 402 with WWW-Authenticate: Payment header
6
+ * 2. MCP level: JSON-RPC error with code -32042 containing MPP data
7
+ */
8
+ const MPP_ERROR_CODE = -32042;
9
+ const REQUIRED_FIELDS = [
10
+ 'id', 'method', 'intent', 'amount', 'currency', 'network', 'recipient'
11
+ ];
12
+ /**
13
+ * Parse MPP challenge from WWW-Authenticate header.
14
+ * Format: Payment method="tempo", intent="charge", id="ch_xxx", ...
15
+ */
16
+ function parseMPPHeader(headerValue) {
17
+ if (!headerValue || !headerValue.startsWith('Payment')) {
18
+ return null;
19
+ }
20
+ // Strip leading "Payment" keyword
21
+ const paramString = headerValue.slice('Payment'.length).trim();
22
+ if (!paramString) {
23
+ return null;
24
+ }
25
+ // Parse key="value" pairs
26
+ const params = {};
27
+ const regex = /(\w+)="([^"]*)"/g;
28
+ let match;
29
+ while ((match = regex.exec(paramString)) !== null) {
30
+ params[match[1]] = match[2];
31
+ }
32
+ // Validate all required fields are present
33
+ for (const field of REQUIRED_FIELDS) {
34
+ if (!params[field]) {
35
+ return null;
36
+ }
37
+ }
38
+ return {
39
+ id: params.id,
40
+ method: params.method,
41
+ intent: params.intent,
42
+ amount: params.amount,
43
+ currency: params.currency,
44
+ network: params.network,
45
+ recipient: params.recipient,
46
+ };
47
+ }
48
+ /**
49
+ * Parse MPP challenge from MCP JSON-RPC error data.
50
+ */
51
+ function parseMPPFromMCPError(errorData) {
52
+ if (typeof errorData !== 'object' || errorData === null) {
53
+ return null;
54
+ }
55
+ const data = errorData;
56
+ const mpp = data.mpp;
57
+ if (typeof mpp !== 'object' || mpp === null) {
58
+ return null;
59
+ }
60
+ const mppObj = mpp;
61
+ // Validate all required fields
62
+ for (const field of REQUIRED_FIELDS) {
63
+ if (typeof mppObj[field] !== 'string') {
64
+ return null;
65
+ }
66
+ }
67
+ return {
68
+ id: mppObj.id,
69
+ method: mppObj.method,
70
+ intent: mppObj.intent,
71
+ amount: mppObj.amount,
72
+ currency: mppObj.currency,
73
+ network: mppObj.network,
74
+ recipient: mppObj.recipient,
75
+ };
76
+ }
77
+ /**
78
+ * Check if a Response has an MPP challenge (via WWW-Authenticate header).
79
+ */
80
+ function hasMPPChallenge(response) {
81
+ const header = response.headers.get('WWW-Authenticate');
82
+ if (!header)
83
+ return false;
84
+ return header.startsWith('Payment');
85
+ }
86
+ /**
87
+ * Check if a Response body contains an MCP error with MPP data.
88
+ * Clones the response so the original body is not consumed.
89
+ */
90
+ async function hasMPPMCPError(response) {
91
+ try {
92
+ const cloned = response.clone();
93
+ const body = await cloned.text();
94
+ if (!body)
95
+ return false;
96
+ const parsed = JSON.parse(body);
97
+ if (typeof parsed === 'object' &&
98
+ parsed !== null &&
99
+ typeof parsed.error === 'object' &&
100
+ parsed.error !== null &&
101
+ parsed.error.code === MPP_ERROR_CODE) {
102
+ const challenge = parseMPPFromMCPError(parsed.error.data);
103
+ return challenge !== null;
104
+ }
105
+ return false;
106
+ }
107
+ catch {
108
+ return false;
109
+ }
110
+ }
111
+
112
+ export { MPP_ERROR_CODE, hasMPPChallenge, hasMPPMCPError, parseMPPFromMCPError, parseMPPHeader };
113
+ //# sourceMappingURL=mppChallenge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mppChallenge.js","sources":["../src/mppChallenge.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@atxp/mpp",
3
+ "version": "0.10.7",
4
+ "description": "ATXP MPP (Machine Payments Protocol) support",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/atxp-dev/sdk.git",
9
+ "directory": "packages/atxp-mpp"
10
+ },
11
+ "type": "module",
12
+ "sideEffects": false,
13
+ "main": "./dist/index.cjs",
14
+ "module": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js",
20
+ "require": "./dist/index.cjs"
21
+ }
22
+ },
23
+ "files": ["dist"],
24
+ "scripts": {
25
+ "build": "rollup -c",
26
+ "typecheck": "tsc --noEmit",
27
+ "lint": "eslint . --ext .ts",
28
+ "lint:fix": "eslint . --ext .ts --fix",
29
+ "test": "vitest run",
30
+ "prepack": "npm run build && npm run typecheck",
31
+ "pack:dry": "npm pack --dry-run"
32
+ },
33
+ "dependencies": {},
34
+ "devDependencies": {
35
+ "@types/node": "^25.0.3",
36
+ "@typescript-eslint/eslint-plugin": "^8.51.0",
37
+ "@typescript-eslint/parser": "^8.51.0",
38
+ "eslint": "^9.32.0",
39
+ "typescript": "^5.7.3",
40
+ "vitest": "^4.0.16"
41
+ }
42
+ }