@openfacilitator/sdk 0.1.0

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 ADDED
@@ -0,0 +1,160 @@
1
+ # @openfacilitator/sdk
2
+
3
+ TypeScript SDK for x402 payment facilitation. Works with OpenFacilitator or any x402-compatible facilitator.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @openfacilitator/sdk
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { OpenFacilitator } from '@openfacilitator/sdk';
15
+
16
+ // Use custom facilitator
17
+ const facilitator = new OpenFacilitator({
18
+ url: 'https://pay.yourdomain.com',
19
+ });
20
+
21
+ // Or use the default OpenFacilitator
22
+ import { createDefaultFacilitator } from '@openfacilitator/sdk';
23
+ const facilitator = createDefaultFacilitator();
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ### Verify a Payment
29
+
30
+ ```typescript
31
+ const result = await facilitator.verify({
32
+ x402Version: 1,
33
+ scheme: 'exact',
34
+ network: 'base',
35
+ payload: {
36
+ signature: '0x...',
37
+ authorization: {
38
+ from: '0x...',
39
+ to: '0x...',
40
+ amount: '1000000',
41
+ asset: '0x...',
42
+ },
43
+ },
44
+ });
45
+
46
+ if (result.valid) {
47
+ console.log('Payment is valid!');
48
+ } else {
49
+ console.error('Invalid payment:', result.error);
50
+ }
51
+ ```
52
+
53
+ ### Settle a Payment
54
+
55
+ ```typescript
56
+ const result = await facilitator.settle({
57
+ x402Version: 1,
58
+ scheme: 'exact',
59
+ network: 'base',
60
+ payload: {
61
+ signature: '0x...',
62
+ authorization: {
63
+ from: '0x...',
64
+ to: '0x...',
65
+ amount: '1000000',
66
+ asset: '0x...',
67
+ },
68
+ },
69
+ });
70
+
71
+ if (result.success) {
72
+ console.log('Transaction hash:', result.transactionHash);
73
+ } else {
74
+ console.error('Settlement failed:', result.error);
75
+ }
76
+ ```
77
+
78
+ ### Get Supported Networks
79
+
80
+ ```typescript
81
+ const supported = await facilitator.supported();
82
+
83
+ console.log('Supported networks:');
84
+ supported.kinds.forEach(kind => {
85
+ console.log(`- ${kind.network} (v${kind.x402Version})`);
86
+ });
87
+ ```
88
+
89
+ ### Network Utilities
90
+
91
+ ```typescript
92
+ import {
93
+ getNetwork,
94
+ getNetworkType,
95
+ toV2NetworkId,
96
+ NETWORKS,
97
+ } from '@openfacilitator/sdk';
98
+
99
+ // Get network info
100
+ const base = getNetwork('base');
101
+ console.log(base?.chainId); // 8453
102
+
103
+ // Convert v1 to v2 ID
104
+ const v2Id = toV2NetworkId('base'); // 'eip155:8453'
105
+
106
+ // Get all mainnets
107
+ const mainnets = NETWORKS.filter(n => !n.testnet);
108
+ ```
109
+
110
+ ## Error Handling
111
+
112
+ ```typescript
113
+ import {
114
+ FacilitatorError,
115
+ VerificationError,
116
+ SettlementError,
117
+ } from '@openfacilitator/sdk';
118
+
119
+ try {
120
+ await facilitator.settle(payment);
121
+ } catch (error) {
122
+ if (error instanceof SettlementError) {
123
+ console.error('Settlement failed:', error.message);
124
+ } else if (error instanceof FacilitatorError) {
125
+ console.error('Facilitator error:', error.code, error.message);
126
+ }
127
+ }
128
+ ```
129
+
130
+ ## x402 Version Support
131
+
132
+ This SDK supports both x402 v1 and v2:
133
+
134
+ - **v1**: Human-readable network names (`base`, `solana`)
135
+ - **v2**: CAIP-2 chain identifiers (`eip155:8453`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`)
136
+
137
+ ## Supported Networks
138
+
139
+ ### EVM Mainnets
140
+
141
+ | Network | v1 ID | v2 ID (CAIP-2) | Chain ID |
142
+ | --------- | ----------- | ---------------- | -------- |
143
+ | Base | `base` | `eip155:8453` | 8453 |
144
+ | Polygon | `polygon` | `eip155:137` | 137 |
145
+ | Avalanche | `avalanche` | `eip155:43114` | 43114 |
146
+ | Sei | `sei` | `eip155:1329` | 1329 |
147
+ | IoTeX | `iotex` | `eip155:4689` | 4689 |
148
+ | Peaq | `peaq` | `eip155:3338` | 3338 |
149
+ | X Layer | `xlayer` | `eip155:196` | 196 |
150
+
151
+ ### Solana
152
+
153
+ | Network | v1 ID | v2 ID (CAIP-2) |
154
+ | ------------- | --------------- | ---------------------------------------- |
155
+ | Solana | `solana` | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` |
156
+ | Solana Devnet | `solana-devnet` | `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` |
157
+
158
+ ## License
159
+
160
+ MIT
@@ -0,0 +1,197 @@
1
+ interface FacilitatorConfig {
2
+ /** Facilitator URL (e.g., https://pay.honeypot.game) */
3
+ url: string;
4
+ /** Optional timeout in ms (default: 30000) */
5
+ timeout?: number;
6
+ /** Optional custom headers */
7
+ headers?: Record<string, string>;
8
+ }
9
+ /**
10
+ * Payment payload for verification/settlement
11
+ * Supports both x402 v1 and v2 formats
12
+ */
13
+ interface PaymentPayload {
14
+ /** x402 version (1 or 2) */
15
+ x402Version: 1 | 2;
16
+ /** Payment scheme (e.g., "exact") */
17
+ scheme: string;
18
+ /** Network identifier - v1: "base", v2: "eip155:8453" */
19
+ network: string;
20
+ /** Payment details */
21
+ payload: {
22
+ /** Signature of the payment */
23
+ signature: string;
24
+ /** Payment authorization */
25
+ authorization: PaymentAuthorization;
26
+ };
27
+ }
28
+ interface PaymentAuthorization {
29
+ /** Sender address */
30
+ from: string;
31
+ /** Recipient address */
32
+ to: string;
33
+ /** Amount in base units (string to handle large numbers) */
34
+ amount: string;
35
+ /** Token/asset address or identifier */
36
+ asset: string;
37
+ /** Chain ID (for EVM) */
38
+ chainId?: number;
39
+ /** Nonce */
40
+ nonce?: string;
41
+ /** Expiration timestamp */
42
+ validUntil?: number;
43
+ /** Additional fields for specific schemes */
44
+ [key: string]: unknown;
45
+ }
46
+ interface VerifyResponse {
47
+ /** Whether the payment is valid */
48
+ valid: boolean;
49
+ /** Error message if invalid */
50
+ error?: string;
51
+ /** Additional verification details */
52
+ details?: {
53
+ /** Verified amount */
54
+ amount?: string;
55
+ /** Verified recipient */
56
+ recipient?: string;
57
+ /** Payment scheme used */
58
+ scheme?: string;
59
+ };
60
+ }
61
+ interface SettleResponse {
62
+ /** Whether settlement was successful */
63
+ success: boolean;
64
+ /** Transaction hash/signature */
65
+ transactionHash?: string;
66
+ /** Network the transaction was settled on */
67
+ network?: string;
68
+ /** Error message if failed */
69
+ error?: string;
70
+ }
71
+ interface SupportedResponse {
72
+ /** Supported payment kinds */
73
+ kinds: PaymentKind[];
74
+ /** Signer addresses by network namespace */
75
+ signers?: Record<string, string[]>;
76
+ /** Supported extensions */
77
+ extensions?: string[];
78
+ }
79
+ interface PaymentKind {
80
+ /** x402 version */
81
+ x402Version: 1 | 2;
82
+ /** Payment scheme */
83
+ scheme: string;
84
+ /** Network identifier */
85
+ network: string;
86
+ /** Extra data (e.g., feePayer for Solana) */
87
+ extra?: {
88
+ feePayer?: string;
89
+ [key: string]: unknown;
90
+ };
91
+ }
92
+ type NetworkType = 'evm' | 'solana';
93
+ interface NetworkInfo {
94
+ /** v1 identifier (e.g., "base") */
95
+ v1Id: string;
96
+ /** v2 CAIP-2 identifier (e.g., "eip155:8453") */
97
+ v2Id: string;
98
+ /** Human-readable name */
99
+ name: string;
100
+ /** Network type */
101
+ type: NetworkType;
102
+ /** Chain ID (EVM only) */
103
+ chainId?: number;
104
+ /** Whether this is a testnet */
105
+ testnet: boolean;
106
+ }
107
+
108
+ declare class OpenFacilitator {
109
+ private readonly baseUrl;
110
+ private readonly timeout;
111
+ private readonly headers;
112
+ constructor(config: FacilitatorConfig);
113
+ /**
114
+ * Get the facilitator URL
115
+ */
116
+ get url(): string;
117
+ /**
118
+ * Verify a payment is valid
119
+ */
120
+ verify(payment: PaymentPayload): Promise<VerifyResponse>;
121
+ /**
122
+ * Settle/broadcast a payment transaction
123
+ */
124
+ settle(payment: PaymentPayload): Promise<SettleResponse>;
125
+ /**
126
+ * Get supported networks and payment kinds
127
+ */
128
+ supported(): Promise<SupportedResponse>;
129
+ /**
130
+ * Health check - verify facilitator is reachable
131
+ */
132
+ health(): Promise<boolean>;
133
+ /**
134
+ * Internal request helper
135
+ */
136
+ private request;
137
+ }
138
+ /**
139
+ * Create a facilitator client with default OpenFacilitator URL
140
+ */
141
+ declare function createDefaultFacilitator(): OpenFacilitator;
142
+
143
+ declare class FacilitatorError extends Error {
144
+ code: string;
145
+ statusCode?: number | undefined;
146
+ details?: unknown | undefined;
147
+ constructor(message: string, code: string, statusCode?: number | undefined, details?: unknown | undefined);
148
+ }
149
+ declare class NetworkError extends FacilitatorError {
150
+ constructor(message: string, details?: unknown);
151
+ }
152
+ declare class VerificationError extends FacilitatorError {
153
+ constructor(message: string, details?: unknown);
154
+ }
155
+ declare class SettlementError extends FacilitatorError {
156
+ constructor(message: string, details?: unknown);
157
+ }
158
+ declare class ConfigurationError extends FacilitatorError {
159
+ constructor(message: string);
160
+ }
161
+
162
+ declare const NETWORKS: NetworkInfo[];
163
+ /**
164
+ * Get network info by v1 or v2 identifier
165
+ */
166
+ declare function getNetwork(id: string): NetworkInfo | undefined;
167
+ /**
168
+ * Get network type from identifier
169
+ */
170
+ declare function getNetworkType(id: string): 'evm' | 'solana' | undefined;
171
+ /**
172
+ * Convert v1 network ID to v2 (CAIP-2)
173
+ */
174
+ declare function toV2NetworkId(id: string): string;
175
+ /**
176
+ * Convert v2 network ID to v1
177
+ */
178
+ declare function toV1NetworkId(id: string): string;
179
+ /**
180
+ * Check if network ID is valid
181
+ */
182
+ declare function isValidNetwork(id: string): boolean;
183
+ /**
184
+ * Get all mainnet networks
185
+ */
186
+ declare function getMainnets(): NetworkInfo[];
187
+ /**
188
+ * Get all testnet networks
189
+ */
190
+ declare function getTestnets(): NetworkInfo[];
191
+
192
+ /**
193
+ * Type guard for checking if value is a valid payment payload
194
+ */
195
+ declare function isPaymentPayload(value: unknown): value is PaymentPayload;
196
+
197
+ export { ConfigurationError, type FacilitatorConfig, FacilitatorError, NETWORKS, NetworkError, type NetworkInfo, type NetworkType, OpenFacilitator, type PaymentAuthorization, type PaymentKind, type PaymentPayload, type SettleResponse, SettlementError, type SupportedResponse, VerificationError, type VerifyResponse, createDefaultFacilitator, getMainnets, getNetwork, getNetworkType, getTestnets, isPaymentPayload, isValidNetwork, toV1NetworkId, toV2NetworkId };
@@ -0,0 +1,197 @@
1
+ interface FacilitatorConfig {
2
+ /** Facilitator URL (e.g., https://pay.honeypot.game) */
3
+ url: string;
4
+ /** Optional timeout in ms (default: 30000) */
5
+ timeout?: number;
6
+ /** Optional custom headers */
7
+ headers?: Record<string, string>;
8
+ }
9
+ /**
10
+ * Payment payload for verification/settlement
11
+ * Supports both x402 v1 and v2 formats
12
+ */
13
+ interface PaymentPayload {
14
+ /** x402 version (1 or 2) */
15
+ x402Version: 1 | 2;
16
+ /** Payment scheme (e.g., "exact") */
17
+ scheme: string;
18
+ /** Network identifier - v1: "base", v2: "eip155:8453" */
19
+ network: string;
20
+ /** Payment details */
21
+ payload: {
22
+ /** Signature of the payment */
23
+ signature: string;
24
+ /** Payment authorization */
25
+ authorization: PaymentAuthorization;
26
+ };
27
+ }
28
+ interface PaymentAuthorization {
29
+ /** Sender address */
30
+ from: string;
31
+ /** Recipient address */
32
+ to: string;
33
+ /** Amount in base units (string to handle large numbers) */
34
+ amount: string;
35
+ /** Token/asset address or identifier */
36
+ asset: string;
37
+ /** Chain ID (for EVM) */
38
+ chainId?: number;
39
+ /** Nonce */
40
+ nonce?: string;
41
+ /** Expiration timestamp */
42
+ validUntil?: number;
43
+ /** Additional fields for specific schemes */
44
+ [key: string]: unknown;
45
+ }
46
+ interface VerifyResponse {
47
+ /** Whether the payment is valid */
48
+ valid: boolean;
49
+ /** Error message if invalid */
50
+ error?: string;
51
+ /** Additional verification details */
52
+ details?: {
53
+ /** Verified amount */
54
+ amount?: string;
55
+ /** Verified recipient */
56
+ recipient?: string;
57
+ /** Payment scheme used */
58
+ scheme?: string;
59
+ };
60
+ }
61
+ interface SettleResponse {
62
+ /** Whether settlement was successful */
63
+ success: boolean;
64
+ /** Transaction hash/signature */
65
+ transactionHash?: string;
66
+ /** Network the transaction was settled on */
67
+ network?: string;
68
+ /** Error message if failed */
69
+ error?: string;
70
+ }
71
+ interface SupportedResponse {
72
+ /** Supported payment kinds */
73
+ kinds: PaymentKind[];
74
+ /** Signer addresses by network namespace */
75
+ signers?: Record<string, string[]>;
76
+ /** Supported extensions */
77
+ extensions?: string[];
78
+ }
79
+ interface PaymentKind {
80
+ /** x402 version */
81
+ x402Version: 1 | 2;
82
+ /** Payment scheme */
83
+ scheme: string;
84
+ /** Network identifier */
85
+ network: string;
86
+ /** Extra data (e.g., feePayer for Solana) */
87
+ extra?: {
88
+ feePayer?: string;
89
+ [key: string]: unknown;
90
+ };
91
+ }
92
+ type NetworkType = 'evm' | 'solana';
93
+ interface NetworkInfo {
94
+ /** v1 identifier (e.g., "base") */
95
+ v1Id: string;
96
+ /** v2 CAIP-2 identifier (e.g., "eip155:8453") */
97
+ v2Id: string;
98
+ /** Human-readable name */
99
+ name: string;
100
+ /** Network type */
101
+ type: NetworkType;
102
+ /** Chain ID (EVM only) */
103
+ chainId?: number;
104
+ /** Whether this is a testnet */
105
+ testnet: boolean;
106
+ }
107
+
108
+ declare class OpenFacilitator {
109
+ private readonly baseUrl;
110
+ private readonly timeout;
111
+ private readonly headers;
112
+ constructor(config: FacilitatorConfig);
113
+ /**
114
+ * Get the facilitator URL
115
+ */
116
+ get url(): string;
117
+ /**
118
+ * Verify a payment is valid
119
+ */
120
+ verify(payment: PaymentPayload): Promise<VerifyResponse>;
121
+ /**
122
+ * Settle/broadcast a payment transaction
123
+ */
124
+ settle(payment: PaymentPayload): Promise<SettleResponse>;
125
+ /**
126
+ * Get supported networks and payment kinds
127
+ */
128
+ supported(): Promise<SupportedResponse>;
129
+ /**
130
+ * Health check - verify facilitator is reachable
131
+ */
132
+ health(): Promise<boolean>;
133
+ /**
134
+ * Internal request helper
135
+ */
136
+ private request;
137
+ }
138
+ /**
139
+ * Create a facilitator client with default OpenFacilitator URL
140
+ */
141
+ declare function createDefaultFacilitator(): OpenFacilitator;
142
+
143
+ declare class FacilitatorError extends Error {
144
+ code: string;
145
+ statusCode?: number | undefined;
146
+ details?: unknown | undefined;
147
+ constructor(message: string, code: string, statusCode?: number | undefined, details?: unknown | undefined);
148
+ }
149
+ declare class NetworkError extends FacilitatorError {
150
+ constructor(message: string, details?: unknown);
151
+ }
152
+ declare class VerificationError extends FacilitatorError {
153
+ constructor(message: string, details?: unknown);
154
+ }
155
+ declare class SettlementError extends FacilitatorError {
156
+ constructor(message: string, details?: unknown);
157
+ }
158
+ declare class ConfigurationError extends FacilitatorError {
159
+ constructor(message: string);
160
+ }
161
+
162
+ declare const NETWORKS: NetworkInfo[];
163
+ /**
164
+ * Get network info by v1 or v2 identifier
165
+ */
166
+ declare function getNetwork(id: string): NetworkInfo | undefined;
167
+ /**
168
+ * Get network type from identifier
169
+ */
170
+ declare function getNetworkType(id: string): 'evm' | 'solana' | undefined;
171
+ /**
172
+ * Convert v1 network ID to v2 (CAIP-2)
173
+ */
174
+ declare function toV2NetworkId(id: string): string;
175
+ /**
176
+ * Convert v2 network ID to v1
177
+ */
178
+ declare function toV1NetworkId(id: string): string;
179
+ /**
180
+ * Check if network ID is valid
181
+ */
182
+ declare function isValidNetwork(id: string): boolean;
183
+ /**
184
+ * Get all mainnet networks
185
+ */
186
+ declare function getMainnets(): NetworkInfo[];
187
+ /**
188
+ * Get all testnet networks
189
+ */
190
+ declare function getTestnets(): NetworkInfo[];
191
+
192
+ /**
193
+ * Type guard for checking if value is a valid payment payload
194
+ */
195
+ declare function isPaymentPayload(value: unknown): value is PaymentPayload;
196
+
197
+ export { ConfigurationError, type FacilitatorConfig, FacilitatorError, NETWORKS, NetworkError, type NetworkInfo, type NetworkType, OpenFacilitator, type PaymentAuthorization, type PaymentKind, type PaymentPayload, type SettleResponse, SettlementError, type SupportedResponse, VerificationError, type VerifyResponse, createDefaultFacilitator, getMainnets, getNetwork, getNetworkType, getTestnets, isPaymentPayload, isValidNetwork, toV1NetworkId, toV2NetworkId };
package/dist/index.js ADDED
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ConfigurationError: () => ConfigurationError,
24
+ FacilitatorError: () => FacilitatorError,
25
+ NETWORKS: () => NETWORKS,
26
+ NetworkError: () => NetworkError,
27
+ OpenFacilitator: () => OpenFacilitator,
28
+ SettlementError: () => SettlementError,
29
+ VerificationError: () => VerificationError,
30
+ createDefaultFacilitator: () => createDefaultFacilitator,
31
+ getMainnets: () => getMainnets,
32
+ getNetwork: () => getNetwork,
33
+ getNetworkType: () => getNetworkType,
34
+ getTestnets: () => getTestnets,
35
+ isPaymentPayload: () => isPaymentPayload,
36
+ isValidNetwork: () => isValidNetwork,
37
+ toV1NetworkId: () => toV1NetworkId,
38
+ toV2NetworkId: () => toV2NetworkId
39
+ });
40
+ module.exports = __toCommonJS(index_exports);
41
+
42
+ // src/errors.ts
43
+ var FacilitatorError = class extends Error {
44
+ constructor(message, code, statusCode, details) {
45
+ super(message);
46
+ this.code = code;
47
+ this.statusCode = statusCode;
48
+ this.details = details;
49
+ this.name = "FacilitatorError";
50
+ }
51
+ };
52
+ var NetworkError = class extends FacilitatorError {
53
+ constructor(message, details) {
54
+ super(message, "NETWORK_ERROR", void 0, details);
55
+ this.name = "NetworkError";
56
+ }
57
+ };
58
+ var VerificationError = class extends FacilitatorError {
59
+ constructor(message, details) {
60
+ super(message, "VERIFICATION_ERROR", void 0, details);
61
+ this.name = "VerificationError";
62
+ }
63
+ };
64
+ var SettlementError = class extends FacilitatorError {
65
+ constructor(message, details) {
66
+ super(message, "SETTLEMENT_ERROR", void 0, details);
67
+ this.name = "SettlementError";
68
+ }
69
+ };
70
+ var ConfigurationError = class extends FacilitatorError {
71
+ constructor(message) {
72
+ super(message, "CONFIGURATION_ERROR");
73
+ this.name = "ConfigurationError";
74
+ }
75
+ };
76
+
77
+ // src/utils.ts
78
+ function normalizeUrl(url) {
79
+ return url.replace(/\/+$/, "");
80
+ }
81
+ function buildUrl(baseUrl, path) {
82
+ return `${normalizeUrl(baseUrl)}${path}`;
83
+ }
84
+ function isPaymentPayload(value) {
85
+ if (!value || typeof value !== "object") return false;
86
+ const obj = value;
87
+ return (obj.x402Version === 1 || obj.x402Version === 2) && typeof obj.scheme === "string" && typeof obj.network === "string" && obj.payload !== void 0;
88
+ }
89
+
90
+ // src/client.ts
91
+ var DEFAULT_TIMEOUT = 3e4;
92
+ var OpenFacilitator = class {
93
+ constructor(config) {
94
+ if (!config.url) {
95
+ throw new ConfigurationError("Facilitator URL is required");
96
+ }
97
+ this.baseUrl = normalizeUrl(config.url);
98
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
99
+ this.headers = {
100
+ "Content-Type": "application/json",
101
+ ...config.headers
102
+ };
103
+ }
104
+ /**
105
+ * Get the facilitator URL
106
+ */
107
+ get url() {
108
+ return this.baseUrl;
109
+ }
110
+ /**
111
+ * Verify a payment is valid
112
+ */
113
+ async verify(payment) {
114
+ try {
115
+ const response = await this.request("/verify", {
116
+ method: "POST",
117
+ body: JSON.stringify(payment)
118
+ });
119
+ return response;
120
+ } catch (error) {
121
+ if (error instanceof FacilitatorError) throw error;
122
+ throw new VerificationError(
123
+ `Verification failed: ${error instanceof Error ? error.message : "Unknown error"}`,
124
+ error
125
+ );
126
+ }
127
+ }
128
+ /**
129
+ * Settle/broadcast a payment transaction
130
+ */
131
+ async settle(payment) {
132
+ try {
133
+ const response = await this.request("/settle", {
134
+ method: "POST",
135
+ body: JSON.stringify(payment)
136
+ });
137
+ return response;
138
+ } catch (error) {
139
+ if (error instanceof FacilitatorError) throw error;
140
+ throw new SettlementError(
141
+ `Settlement failed: ${error instanceof Error ? error.message : "Unknown error"}`,
142
+ error
143
+ );
144
+ }
145
+ }
146
+ /**
147
+ * Get supported networks and payment kinds
148
+ */
149
+ async supported() {
150
+ try {
151
+ const response = await this.request("/supported", {
152
+ method: "GET"
153
+ });
154
+ return response;
155
+ } catch (error) {
156
+ if (error instanceof FacilitatorError) throw error;
157
+ throw new NetworkError(
158
+ `Failed to fetch supported networks: ${error instanceof Error ? error.message : "Unknown error"}`,
159
+ error
160
+ );
161
+ }
162
+ }
163
+ /**
164
+ * Health check - verify facilitator is reachable
165
+ */
166
+ async health() {
167
+ try {
168
+ await this.supported();
169
+ return true;
170
+ } catch {
171
+ return false;
172
+ }
173
+ }
174
+ /**
175
+ * Internal request helper
176
+ */
177
+ async request(path, init) {
178
+ const url = buildUrl(this.baseUrl, path);
179
+ const controller = new AbortController();
180
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
181
+ try {
182
+ const response = await fetch(url, {
183
+ ...init,
184
+ headers: {
185
+ ...this.headers,
186
+ ...init.headers
187
+ },
188
+ signal: controller.signal
189
+ });
190
+ clearTimeout(timeoutId);
191
+ if (!response.ok) {
192
+ let errorMessage = `HTTP ${response.status}`;
193
+ try {
194
+ const errorBody = await response.json();
195
+ errorMessage = errorBody.error || errorBody.message || errorMessage;
196
+ } catch {
197
+ }
198
+ throw new FacilitatorError(errorMessage, "HTTP_ERROR", response.status);
199
+ }
200
+ return await response.json();
201
+ } catch (error) {
202
+ clearTimeout(timeoutId);
203
+ if (error instanceof FacilitatorError) throw error;
204
+ if (error instanceof Error && error.name === "AbortError") {
205
+ throw new NetworkError(`Request timeout after ${this.timeout}ms`);
206
+ }
207
+ throw new NetworkError(
208
+ `Request failed: ${error instanceof Error ? error.message : "Unknown error"}`,
209
+ error
210
+ );
211
+ }
212
+ }
213
+ };
214
+ function createDefaultFacilitator() {
215
+ return new OpenFacilitator({
216
+ url: "https://x402.openfacilitator.io"
217
+ });
218
+ }
219
+
220
+ // src/networks.ts
221
+ var NETWORKS = [
222
+ // EVM Mainnets
223
+ { v1Id: "base", v2Id: "eip155:8453", name: "Base", type: "evm", chainId: 8453, testnet: false },
224
+ { v1Id: "polygon", v2Id: "eip155:137", name: "Polygon", type: "evm", chainId: 137, testnet: false },
225
+ { v1Id: "avalanche", v2Id: "eip155:43114", name: "Avalanche", type: "evm", chainId: 43114, testnet: false },
226
+ { v1Id: "sei", v2Id: "eip155:1329", name: "Sei", type: "evm", chainId: 1329, testnet: false },
227
+ { v1Id: "iotex", v2Id: "eip155:4689", name: "IoTeX", type: "evm", chainId: 4689, testnet: false },
228
+ { v1Id: "peaq", v2Id: "eip155:3338", name: "Peaq", type: "evm", chainId: 3338, testnet: false },
229
+ { v1Id: "xlayer", v2Id: "eip155:196", name: "X Layer", type: "evm", chainId: 196, testnet: false },
230
+ // EVM Testnets
231
+ { v1Id: "base-sepolia", v2Id: "eip155:84532", name: "Base Sepolia", type: "evm", chainId: 84532, testnet: true },
232
+ { v1Id: "polygon-amoy", v2Id: "eip155:80002", name: "Polygon Amoy", type: "evm", chainId: 80002, testnet: true },
233
+ { v1Id: "avalanche-fuji", v2Id: "eip155:43113", name: "Avalanche Fuji", type: "evm", chainId: 43113, testnet: true },
234
+ { v1Id: "sei-testnet", v2Id: "eip155:1328", name: "Sei Testnet", type: "evm", chainId: 1328, testnet: true },
235
+ { v1Id: "xlayer-testnet", v2Id: "eip155:195", name: "X Layer Testnet", type: "evm", chainId: 195, testnet: true },
236
+ // Solana
237
+ { v1Id: "solana", v2Id: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", name: "Solana", type: "solana", testnet: false },
238
+ { v1Id: "solana-devnet", v2Id: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", name: "Solana Devnet", type: "solana", testnet: true }
239
+ ];
240
+ function getNetwork(id) {
241
+ return NETWORKS.find((n) => n.v1Id === id || n.v2Id === id);
242
+ }
243
+ function getNetworkType(id) {
244
+ const network = getNetwork(id);
245
+ if (network) return network.type;
246
+ if (id.startsWith("eip155:")) return "evm";
247
+ if (id.startsWith("solana:")) return "solana";
248
+ return void 0;
249
+ }
250
+ function toV2NetworkId(id) {
251
+ const network = getNetwork(id);
252
+ return network?.v2Id ?? id;
253
+ }
254
+ function toV1NetworkId(id) {
255
+ const network = getNetwork(id);
256
+ return network?.v1Id ?? id;
257
+ }
258
+ function isValidNetwork(id) {
259
+ return getNetwork(id) !== void 0;
260
+ }
261
+ function getMainnets() {
262
+ return NETWORKS.filter((n) => !n.testnet);
263
+ }
264
+ function getTestnets() {
265
+ return NETWORKS.filter((n) => n.testnet);
266
+ }
267
+ // Annotate the CommonJS export names for ESM import in node:
268
+ 0 && (module.exports = {
269
+ ConfigurationError,
270
+ FacilitatorError,
271
+ NETWORKS,
272
+ NetworkError,
273
+ OpenFacilitator,
274
+ SettlementError,
275
+ VerificationError,
276
+ createDefaultFacilitator,
277
+ getMainnets,
278
+ getNetwork,
279
+ getNetworkType,
280
+ getTestnets,
281
+ isPaymentPayload,
282
+ isValidNetwork,
283
+ toV1NetworkId,
284
+ toV2NetworkId
285
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,243 @@
1
+ // src/errors.ts
2
+ var FacilitatorError = class extends Error {
3
+ constructor(message, code, statusCode, details) {
4
+ super(message);
5
+ this.code = code;
6
+ this.statusCode = statusCode;
7
+ this.details = details;
8
+ this.name = "FacilitatorError";
9
+ }
10
+ };
11
+ var NetworkError = class extends FacilitatorError {
12
+ constructor(message, details) {
13
+ super(message, "NETWORK_ERROR", void 0, details);
14
+ this.name = "NetworkError";
15
+ }
16
+ };
17
+ var VerificationError = class extends FacilitatorError {
18
+ constructor(message, details) {
19
+ super(message, "VERIFICATION_ERROR", void 0, details);
20
+ this.name = "VerificationError";
21
+ }
22
+ };
23
+ var SettlementError = class extends FacilitatorError {
24
+ constructor(message, details) {
25
+ super(message, "SETTLEMENT_ERROR", void 0, details);
26
+ this.name = "SettlementError";
27
+ }
28
+ };
29
+ var ConfigurationError = class extends FacilitatorError {
30
+ constructor(message) {
31
+ super(message, "CONFIGURATION_ERROR");
32
+ this.name = "ConfigurationError";
33
+ }
34
+ };
35
+
36
+ // src/utils.ts
37
+ function normalizeUrl(url) {
38
+ return url.replace(/\/+$/, "");
39
+ }
40
+ function buildUrl(baseUrl, path) {
41
+ return `${normalizeUrl(baseUrl)}${path}`;
42
+ }
43
+ function isPaymentPayload(value) {
44
+ if (!value || typeof value !== "object") return false;
45
+ const obj = value;
46
+ return (obj.x402Version === 1 || obj.x402Version === 2) && typeof obj.scheme === "string" && typeof obj.network === "string" && obj.payload !== void 0;
47
+ }
48
+
49
+ // src/client.ts
50
+ var DEFAULT_TIMEOUT = 3e4;
51
+ var OpenFacilitator = class {
52
+ constructor(config) {
53
+ if (!config.url) {
54
+ throw new ConfigurationError("Facilitator URL is required");
55
+ }
56
+ this.baseUrl = normalizeUrl(config.url);
57
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
58
+ this.headers = {
59
+ "Content-Type": "application/json",
60
+ ...config.headers
61
+ };
62
+ }
63
+ /**
64
+ * Get the facilitator URL
65
+ */
66
+ get url() {
67
+ return this.baseUrl;
68
+ }
69
+ /**
70
+ * Verify a payment is valid
71
+ */
72
+ async verify(payment) {
73
+ try {
74
+ const response = await this.request("/verify", {
75
+ method: "POST",
76
+ body: JSON.stringify(payment)
77
+ });
78
+ return response;
79
+ } catch (error) {
80
+ if (error instanceof FacilitatorError) throw error;
81
+ throw new VerificationError(
82
+ `Verification failed: ${error instanceof Error ? error.message : "Unknown error"}`,
83
+ error
84
+ );
85
+ }
86
+ }
87
+ /**
88
+ * Settle/broadcast a payment transaction
89
+ */
90
+ async settle(payment) {
91
+ try {
92
+ const response = await this.request("/settle", {
93
+ method: "POST",
94
+ body: JSON.stringify(payment)
95
+ });
96
+ return response;
97
+ } catch (error) {
98
+ if (error instanceof FacilitatorError) throw error;
99
+ throw new SettlementError(
100
+ `Settlement failed: ${error instanceof Error ? error.message : "Unknown error"}`,
101
+ error
102
+ );
103
+ }
104
+ }
105
+ /**
106
+ * Get supported networks and payment kinds
107
+ */
108
+ async supported() {
109
+ try {
110
+ const response = await this.request("/supported", {
111
+ method: "GET"
112
+ });
113
+ return response;
114
+ } catch (error) {
115
+ if (error instanceof FacilitatorError) throw error;
116
+ throw new NetworkError(
117
+ `Failed to fetch supported networks: ${error instanceof Error ? error.message : "Unknown error"}`,
118
+ error
119
+ );
120
+ }
121
+ }
122
+ /**
123
+ * Health check - verify facilitator is reachable
124
+ */
125
+ async health() {
126
+ try {
127
+ await this.supported();
128
+ return true;
129
+ } catch {
130
+ return false;
131
+ }
132
+ }
133
+ /**
134
+ * Internal request helper
135
+ */
136
+ async request(path, init) {
137
+ const url = buildUrl(this.baseUrl, path);
138
+ const controller = new AbortController();
139
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
140
+ try {
141
+ const response = await fetch(url, {
142
+ ...init,
143
+ headers: {
144
+ ...this.headers,
145
+ ...init.headers
146
+ },
147
+ signal: controller.signal
148
+ });
149
+ clearTimeout(timeoutId);
150
+ if (!response.ok) {
151
+ let errorMessage = `HTTP ${response.status}`;
152
+ try {
153
+ const errorBody = await response.json();
154
+ errorMessage = errorBody.error || errorBody.message || errorMessage;
155
+ } catch {
156
+ }
157
+ throw new FacilitatorError(errorMessage, "HTTP_ERROR", response.status);
158
+ }
159
+ return await response.json();
160
+ } catch (error) {
161
+ clearTimeout(timeoutId);
162
+ if (error instanceof FacilitatorError) throw error;
163
+ if (error instanceof Error && error.name === "AbortError") {
164
+ throw new NetworkError(`Request timeout after ${this.timeout}ms`);
165
+ }
166
+ throw new NetworkError(
167
+ `Request failed: ${error instanceof Error ? error.message : "Unknown error"}`,
168
+ error
169
+ );
170
+ }
171
+ }
172
+ };
173
+ function createDefaultFacilitator() {
174
+ return new OpenFacilitator({
175
+ url: "https://x402.openfacilitator.io"
176
+ });
177
+ }
178
+
179
+ // src/networks.ts
180
+ var NETWORKS = [
181
+ // EVM Mainnets
182
+ { v1Id: "base", v2Id: "eip155:8453", name: "Base", type: "evm", chainId: 8453, testnet: false },
183
+ { v1Id: "polygon", v2Id: "eip155:137", name: "Polygon", type: "evm", chainId: 137, testnet: false },
184
+ { v1Id: "avalanche", v2Id: "eip155:43114", name: "Avalanche", type: "evm", chainId: 43114, testnet: false },
185
+ { v1Id: "sei", v2Id: "eip155:1329", name: "Sei", type: "evm", chainId: 1329, testnet: false },
186
+ { v1Id: "iotex", v2Id: "eip155:4689", name: "IoTeX", type: "evm", chainId: 4689, testnet: false },
187
+ { v1Id: "peaq", v2Id: "eip155:3338", name: "Peaq", type: "evm", chainId: 3338, testnet: false },
188
+ { v1Id: "xlayer", v2Id: "eip155:196", name: "X Layer", type: "evm", chainId: 196, testnet: false },
189
+ // EVM Testnets
190
+ { v1Id: "base-sepolia", v2Id: "eip155:84532", name: "Base Sepolia", type: "evm", chainId: 84532, testnet: true },
191
+ { v1Id: "polygon-amoy", v2Id: "eip155:80002", name: "Polygon Amoy", type: "evm", chainId: 80002, testnet: true },
192
+ { v1Id: "avalanche-fuji", v2Id: "eip155:43113", name: "Avalanche Fuji", type: "evm", chainId: 43113, testnet: true },
193
+ { v1Id: "sei-testnet", v2Id: "eip155:1328", name: "Sei Testnet", type: "evm", chainId: 1328, testnet: true },
194
+ { v1Id: "xlayer-testnet", v2Id: "eip155:195", name: "X Layer Testnet", type: "evm", chainId: 195, testnet: true },
195
+ // Solana
196
+ { v1Id: "solana", v2Id: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", name: "Solana", type: "solana", testnet: false },
197
+ { v1Id: "solana-devnet", v2Id: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", name: "Solana Devnet", type: "solana", testnet: true }
198
+ ];
199
+ function getNetwork(id) {
200
+ return NETWORKS.find((n) => n.v1Id === id || n.v2Id === id);
201
+ }
202
+ function getNetworkType(id) {
203
+ const network = getNetwork(id);
204
+ if (network) return network.type;
205
+ if (id.startsWith("eip155:")) return "evm";
206
+ if (id.startsWith("solana:")) return "solana";
207
+ return void 0;
208
+ }
209
+ function toV2NetworkId(id) {
210
+ const network = getNetwork(id);
211
+ return network?.v2Id ?? id;
212
+ }
213
+ function toV1NetworkId(id) {
214
+ const network = getNetwork(id);
215
+ return network?.v1Id ?? id;
216
+ }
217
+ function isValidNetwork(id) {
218
+ return getNetwork(id) !== void 0;
219
+ }
220
+ function getMainnets() {
221
+ return NETWORKS.filter((n) => !n.testnet);
222
+ }
223
+ function getTestnets() {
224
+ return NETWORKS.filter((n) => n.testnet);
225
+ }
226
+ export {
227
+ ConfigurationError,
228
+ FacilitatorError,
229
+ NETWORKS,
230
+ NetworkError,
231
+ OpenFacilitator,
232
+ SettlementError,
233
+ VerificationError,
234
+ createDefaultFacilitator,
235
+ getMainnets,
236
+ getNetwork,
237
+ getNetworkType,
238
+ getTestnets,
239
+ isPaymentPayload,
240
+ isValidNetwork,
241
+ toV1NetworkId,
242
+ toV2NetworkId
243
+ };
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@openfacilitator/sdk",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript SDK for x402 payment facilitation",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "tsup src/index.ts --format cjs,esm --dts",
13
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
14
+ "test": "vitest",
15
+ "lint": "eslint src/",
16
+ "clean": "rm -rf dist"
17
+ },
18
+ "keywords": [
19
+ "x402",
20
+ "payments",
21
+ "crypto",
22
+ "facilitator",
23
+ "solana",
24
+ "evm",
25
+ "base"
26
+ ],
27
+ "author": "",
28
+ "license": "MIT",
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/your-repo/openfacilitator"
32
+ },
33
+ "devDependencies": {
34
+ "tsup": "^8.0.0",
35
+ "typescript": "^5.0.0",
36
+ "vitest": "^1.0.0"
37
+ },
38
+ "engines": {
39
+ "node": ">=18"
40
+ }
41
+ }