@wtflabs/x402-facilitator 0.0.1-beta.2
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 -0
- package/dist/index.d.mts +163 -0
- package/dist/index.d.ts +163 -0
- package/dist/index.js +192 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +165 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# @wtflabs/x402-facilitator
|
|
2
|
+
|
|
3
|
+
X402 支付协议的 Facilitator,用于处理支付验证和结算。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @wtflabs/x402-facilitator
|
|
9
|
+
# 或
|
|
10
|
+
pnpm add @wtflabs/x402-facilitator
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 使用
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { Facilitator } from "@wtflabs/x402-facilitator";
|
|
17
|
+
|
|
18
|
+
// 创建 Facilitator 实例
|
|
19
|
+
const facilitator = new Facilitator({
|
|
20
|
+
recipientAddress: "0x1234...", // 商家地址 (EIP 7702)
|
|
21
|
+
relayer: "0x5678...", // 可选,内置 WTF Facilitator
|
|
22
|
+
waitUntil: "confirmed", // 可选: "simulated" | "submitted" | "confirmed"
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// 验证支付
|
|
26
|
+
const verifyResult = await facilitator.verify(
|
|
27
|
+
paymentPayload,
|
|
28
|
+
paymentRequirements
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
if (verifyResult.success) {
|
|
32
|
+
console.log("支付验证成功!支付者:", verifyResult.payer);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// 结算支付
|
|
36
|
+
const settleResult = await facilitator.settle(
|
|
37
|
+
paymentPayload,
|
|
38
|
+
paymentRequirements
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
if (settleResult.success) {
|
|
42
|
+
console.log("支付结算成功!交易哈希:", settleResult.transactionHash);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 获取支持的支付类型
|
|
46
|
+
const supported = await facilitator.supported();
|
|
47
|
+
console.log("支持的支付类型:", supported.kinds);
|
|
48
|
+
|
|
49
|
+
// 带过滤条件查询
|
|
50
|
+
const filteredSupported = await facilitator.supported({
|
|
51
|
+
chainId: 97,
|
|
52
|
+
tokenAddress: "0xabc...",
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## API
|
|
57
|
+
|
|
58
|
+
### `Facilitator`
|
|
59
|
+
|
|
60
|
+
#### 构造函数
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
new Facilitator(config: FacilitatorConfig)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**配置选项 (`FacilitatorConfig`):**
|
|
67
|
+
|
|
68
|
+
- `recipientAddress` (必需): 商家地址,支持 EIP 7702
|
|
69
|
+
- `relayer` (可选): 中继地址,默认使用内置 WTF Facilitator
|
|
70
|
+
- `waitUntil` (可选): 等待策略
|
|
71
|
+
- `"simulated"`: 仅模拟交易 (最快)
|
|
72
|
+
- `"submitted"`: 等待交易提交
|
|
73
|
+
- `"confirmed"`: 等待链上确认 (最安全,默认)
|
|
74
|
+
- `baseUrl` (可选): Facilitator API 基础 URL
|
|
75
|
+
- `apiKey` (可选): API 密钥
|
|
76
|
+
|
|
77
|
+
#### 属性
|
|
78
|
+
|
|
79
|
+
- `relayer`: 获取 relayer 地址
|
|
80
|
+
- `recipientAddress`: 获取 recipient 地址
|
|
81
|
+
- `waitUntil`: 获取等待策略
|
|
82
|
+
|
|
83
|
+
#### 方法
|
|
84
|
+
|
|
85
|
+
##### `verify(payload, requirements)`
|
|
86
|
+
|
|
87
|
+
验证支付。
|
|
88
|
+
|
|
89
|
+
- **参数:**
|
|
90
|
+
- `payload`: 支付负载
|
|
91
|
+
- `requirements`: 支付要求
|
|
92
|
+
- **返回:** `Promise<VerifyResponse>`
|
|
93
|
+
|
|
94
|
+
##### `settle(payload, requirements, waitUntil?)`
|
|
95
|
+
|
|
96
|
+
结算支付。
|
|
97
|
+
|
|
98
|
+
- **参数:**
|
|
99
|
+
- `payload`: 支付负载
|
|
100
|
+
- `requirements`: 支付要求
|
|
101
|
+
- `waitUntil` (可选): 等待策略,覆盖配置中的默认值
|
|
102
|
+
- **返回:** `Promise<SettleResponse>`
|
|
103
|
+
|
|
104
|
+
##### `supported(filters?)`
|
|
105
|
+
|
|
106
|
+
获取支持的支付类型。
|
|
107
|
+
|
|
108
|
+
- **参数:**
|
|
109
|
+
- `filters` (可选): 过滤条件
|
|
110
|
+
- `chainId`: 链 ID
|
|
111
|
+
- `tokenAddress`: 代币地址
|
|
112
|
+
- **返回:** `Promise<SupportedResponse>`
|
|
113
|
+
|
|
114
|
+
##### `getConfig()`
|
|
115
|
+
|
|
116
|
+
获取完整配置。
|
|
117
|
+
|
|
118
|
+
- **返回:** `Required<FacilitatorConfig>`
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
Apache-2.0
|
|
123
|
+
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Facilitator 等待策略
|
|
3
|
+
*/
|
|
4
|
+
type WaitUntil = "simulated" | "submitted" | "confirmed";
|
|
5
|
+
/**
|
|
6
|
+
* Facilitator 配置选项
|
|
7
|
+
*/
|
|
8
|
+
interface FacilitatorConfig {
|
|
9
|
+
/**
|
|
10
|
+
* 商家地址 (收款地址,支持 EIP 7702)
|
|
11
|
+
*/
|
|
12
|
+
recipientAddress: string;
|
|
13
|
+
/**
|
|
14
|
+
* 中继地址 (可选,默认使用内置 WTF Facilitator)
|
|
15
|
+
*/
|
|
16
|
+
relayer?: string;
|
|
17
|
+
/**
|
|
18
|
+
* 等待策略
|
|
19
|
+
* - "simulated": 仅模拟交易 (最快)
|
|
20
|
+
* - "submitted": 等待交易提交
|
|
21
|
+
* - "confirmed": 等待链上确认 (最安全,默认)
|
|
22
|
+
*/
|
|
23
|
+
waitUntil?: WaitUntil;
|
|
24
|
+
/**
|
|
25
|
+
* Facilitator API 基础 URL (可选)
|
|
26
|
+
*/
|
|
27
|
+
baseUrl?: string;
|
|
28
|
+
/**
|
|
29
|
+
* API 密钥 (可选)
|
|
30
|
+
*/
|
|
31
|
+
apiKey?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 支付负载
|
|
35
|
+
*/
|
|
36
|
+
interface PaymentPayload {
|
|
37
|
+
x402Version: number;
|
|
38
|
+
scheme: string;
|
|
39
|
+
network: string;
|
|
40
|
+
payload: any;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 支付要求
|
|
44
|
+
*/
|
|
45
|
+
interface PaymentRequirements {
|
|
46
|
+
scheme: string;
|
|
47
|
+
network: string;
|
|
48
|
+
maxAmountRequired: string;
|
|
49
|
+
resource: string;
|
|
50
|
+
description: string;
|
|
51
|
+
mimeType: string;
|
|
52
|
+
payTo: string;
|
|
53
|
+
maxTimeoutSeconds: number;
|
|
54
|
+
asset: string;
|
|
55
|
+
extra?: Record<string, any>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 验证响应
|
|
59
|
+
*/
|
|
60
|
+
interface VerifyResponse {
|
|
61
|
+
success: boolean;
|
|
62
|
+
payer?: string;
|
|
63
|
+
error?: string;
|
|
64
|
+
errorMessage?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 结算响应
|
|
68
|
+
*/
|
|
69
|
+
interface SettleResponse {
|
|
70
|
+
success: boolean;
|
|
71
|
+
transactionHash?: string;
|
|
72
|
+
network?: string;
|
|
73
|
+
error?: string;
|
|
74
|
+
errorMessage?: string;
|
|
75
|
+
receipt?: any;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 支持的支付类型响应
|
|
79
|
+
*/
|
|
80
|
+
interface SupportedResponse {
|
|
81
|
+
kinds: Array<{
|
|
82
|
+
x402Version: number;
|
|
83
|
+
scheme: string;
|
|
84
|
+
network: string;
|
|
85
|
+
extra?: Record<string, any>;
|
|
86
|
+
}>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Facilitator 类
|
|
91
|
+
* 用于处理支付验证和结算
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const facilitator = new Facilitator({
|
|
96
|
+
* recipientAddress: "0x1234...",
|
|
97
|
+
* relayer: "0x5678...", // 可选
|
|
98
|
+
* waitUntil: "confirmed", // 可选
|
|
99
|
+
* });
|
|
100
|
+
*
|
|
101
|
+
* // 验证支付
|
|
102
|
+
* const verifyResult = await facilitator.verify(
|
|
103
|
+
* paymentPayload,
|
|
104
|
+
* paymentRequirements
|
|
105
|
+
* );
|
|
106
|
+
*
|
|
107
|
+
* // 结算支付
|
|
108
|
+
* const settleResult = await facilitator.settle(
|
|
109
|
+
* paymentPayload,
|
|
110
|
+
* paymentRequirements
|
|
111
|
+
* );
|
|
112
|
+
*
|
|
113
|
+
* // 获取支持的支付类型
|
|
114
|
+
* const supported = await facilitator.supported();
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
declare class Facilitator {
|
|
118
|
+
private config;
|
|
119
|
+
private authHeaders;
|
|
120
|
+
constructor(config: FacilitatorConfig);
|
|
121
|
+
/**
|
|
122
|
+
* 获取 relayer 地址
|
|
123
|
+
*/
|
|
124
|
+
get relayer(): string;
|
|
125
|
+
/**
|
|
126
|
+
* 获取 recipient 地址
|
|
127
|
+
*/
|
|
128
|
+
get recipientAddress(): string;
|
|
129
|
+
/**
|
|
130
|
+
* 获取等待策略
|
|
131
|
+
*/
|
|
132
|
+
get waitUntil(): WaitUntil;
|
|
133
|
+
/**
|
|
134
|
+
* 验证支付
|
|
135
|
+
* @param payload 支付负载
|
|
136
|
+
* @param requirements 支付要求
|
|
137
|
+
* @returns 验证结果
|
|
138
|
+
*/
|
|
139
|
+
verify(payload: PaymentPayload, requirements: PaymentRequirements): Promise<VerifyResponse>;
|
|
140
|
+
/**
|
|
141
|
+
* 结算支付
|
|
142
|
+
* @param payload 支付负载
|
|
143
|
+
* @param requirements 支付要求
|
|
144
|
+
* @param waitUntil 可选的等待策略,覆盖配置中的默认值
|
|
145
|
+
* @returns 结算结果
|
|
146
|
+
*/
|
|
147
|
+
settle(payload: PaymentPayload, requirements: PaymentRequirements, waitUntil?: WaitUntil): Promise<SettleResponse>;
|
|
148
|
+
/**
|
|
149
|
+
* 获取支持的支付类型
|
|
150
|
+
* @param filters 可选的过滤条件
|
|
151
|
+
* @returns 支持的支付类型列表
|
|
152
|
+
*/
|
|
153
|
+
supported(filters?: {
|
|
154
|
+
chainId?: number;
|
|
155
|
+
tokenAddress?: string;
|
|
156
|
+
}): Promise<SupportedResponse>;
|
|
157
|
+
/**
|
|
158
|
+
* 获取完整配置
|
|
159
|
+
*/
|
|
160
|
+
getConfig(): Required<FacilitatorConfig>;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export { Facilitator, type FacilitatorConfig, type PaymentPayload, type PaymentRequirements, type SettleResponse, type SupportedResponse, type VerifyResponse, type WaitUntil };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Facilitator 等待策略
|
|
3
|
+
*/
|
|
4
|
+
type WaitUntil = "simulated" | "submitted" | "confirmed";
|
|
5
|
+
/**
|
|
6
|
+
* Facilitator 配置选项
|
|
7
|
+
*/
|
|
8
|
+
interface FacilitatorConfig {
|
|
9
|
+
/**
|
|
10
|
+
* 商家地址 (收款地址,支持 EIP 7702)
|
|
11
|
+
*/
|
|
12
|
+
recipientAddress: string;
|
|
13
|
+
/**
|
|
14
|
+
* 中继地址 (可选,默认使用内置 WTF Facilitator)
|
|
15
|
+
*/
|
|
16
|
+
relayer?: string;
|
|
17
|
+
/**
|
|
18
|
+
* 等待策略
|
|
19
|
+
* - "simulated": 仅模拟交易 (最快)
|
|
20
|
+
* - "submitted": 等待交易提交
|
|
21
|
+
* - "confirmed": 等待链上确认 (最安全,默认)
|
|
22
|
+
*/
|
|
23
|
+
waitUntil?: WaitUntil;
|
|
24
|
+
/**
|
|
25
|
+
* Facilitator API 基础 URL (可选)
|
|
26
|
+
*/
|
|
27
|
+
baseUrl?: string;
|
|
28
|
+
/**
|
|
29
|
+
* API 密钥 (可选)
|
|
30
|
+
*/
|
|
31
|
+
apiKey?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 支付负载
|
|
35
|
+
*/
|
|
36
|
+
interface PaymentPayload {
|
|
37
|
+
x402Version: number;
|
|
38
|
+
scheme: string;
|
|
39
|
+
network: string;
|
|
40
|
+
payload: any;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 支付要求
|
|
44
|
+
*/
|
|
45
|
+
interface PaymentRequirements {
|
|
46
|
+
scheme: string;
|
|
47
|
+
network: string;
|
|
48
|
+
maxAmountRequired: string;
|
|
49
|
+
resource: string;
|
|
50
|
+
description: string;
|
|
51
|
+
mimeType: string;
|
|
52
|
+
payTo: string;
|
|
53
|
+
maxTimeoutSeconds: number;
|
|
54
|
+
asset: string;
|
|
55
|
+
extra?: Record<string, any>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 验证响应
|
|
59
|
+
*/
|
|
60
|
+
interface VerifyResponse {
|
|
61
|
+
success: boolean;
|
|
62
|
+
payer?: string;
|
|
63
|
+
error?: string;
|
|
64
|
+
errorMessage?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 结算响应
|
|
68
|
+
*/
|
|
69
|
+
interface SettleResponse {
|
|
70
|
+
success: boolean;
|
|
71
|
+
transactionHash?: string;
|
|
72
|
+
network?: string;
|
|
73
|
+
error?: string;
|
|
74
|
+
errorMessage?: string;
|
|
75
|
+
receipt?: any;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 支持的支付类型响应
|
|
79
|
+
*/
|
|
80
|
+
interface SupportedResponse {
|
|
81
|
+
kinds: Array<{
|
|
82
|
+
x402Version: number;
|
|
83
|
+
scheme: string;
|
|
84
|
+
network: string;
|
|
85
|
+
extra?: Record<string, any>;
|
|
86
|
+
}>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Facilitator 类
|
|
91
|
+
* 用于处理支付验证和结算
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const facilitator = new Facilitator({
|
|
96
|
+
* recipientAddress: "0x1234...",
|
|
97
|
+
* relayer: "0x5678...", // 可选
|
|
98
|
+
* waitUntil: "confirmed", // 可选
|
|
99
|
+
* });
|
|
100
|
+
*
|
|
101
|
+
* // 验证支付
|
|
102
|
+
* const verifyResult = await facilitator.verify(
|
|
103
|
+
* paymentPayload,
|
|
104
|
+
* paymentRequirements
|
|
105
|
+
* );
|
|
106
|
+
*
|
|
107
|
+
* // 结算支付
|
|
108
|
+
* const settleResult = await facilitator.settle(
|
|
109
|
+
* paymentPayload,
|
|
110
|
+
* paymentRequirements
|
|
111
|
+
* );
|
|
112
|
+
*
|
|
113
|
+
* // 获取支持的支付类型
|
|
114
|
+
* const supported = await facilitator.supported();
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
declare class Facilitator {
|
|
118
|
+
private config;
|
|
119
|
+
private authHeaders;
|
|
120
|
+
constructor(config: FacilitatorConfig);
|
|
121
|
+
/**
|
|
122
|
+
* 获取 relayer 地址
|
|
123
|
+
*/
|
|
124
|
+
get relayer(): string;
|
|
125
|
+
/**
|
|
126
|
+
* 获取 recipient 地址
|
|
127
|
+
*/
|
|
128
|
+
get recipientAddress(): string;
|
|
129
|
+
/**
|
|
130
|
+
* 获取等待策略
|
|
131
|
+
*/
|
|
132
|
+
get waitUntil(): WaitUntil;
|
|
133
|
+
/**
|
|
134
|
+
* 验证支付
|
|
135
|
+
* @param payload 支付负载
|
|
136
|
+
* @param requirements 支付要求
|
|
137
|
+
* @returns 验证结果
|
|
138
|
+
*/
|
|
139
|
+
verify(payload: PaymentPayload, requirements: PaymentRequirements): Promise<VerifyResponse>;
|
|
140
|
+
/**
|
|
141
|
+
* 结算支付
|
|
142
|
+
* @param payload 支付负载
|
|
143
|
+
* @param requirements 支付要求
|
|
144
|
+
* @param waitUntil 可选的等待策略,覆盖配置中的默认值
|
|
145
|
+
* @returns 结算结果
|
|
146
|
+
*/
|
|
147
|
+
settle(payload: PaymentPayload, requirements: PaymentRequirements, waitUntil?: WaitUntil): Promise<SettleResponse>;
|
|
148
|
+
/**
|
|
149
|
+
* 获取支持的支付类型
|
|
150
|
+
* @param filters 可选的过滤条件
|
|
151
|
+
* @returns 支持的支付类型列表
|
|
152
|
+
*/
|
|
153
|
+
supported(filters?: {
|
|
154
|
+
chainId?: number;
|
|
155
|
+
tokenAddress?: string;
|
|
156
|
+
}): Promise<SupportedResponse>;
|
|
157
|
+
/**
|
|
158
|
+
* 获取完整配置
|
|
159
|
+
*/
|
|
160
|
+
getConfig(): Required<FacilitatorConfig>;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export { Facilitator, type FacilitatorConfig, type PaymentPayload, type PaymentRequirements, type SettleResponse, type SupportedResponse, type VerifyResponse, type WaitUntil };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
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
|
+
Facilitator: () => Facilitator
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/facilitator.ts
|
|
28
|
+
var DEFAULT_FACILITATOR_URL = "https://facilitator.wtf.com/v1";
|
|
29
|
+
var DEFAULT_RELAYER_ADDRESS = "0x877D0A51a37178b5F34Ffb68a5c2beD0ff46D432";
|
|
30
|
+
var Facilitator = class {
|
|
31
|
+
constructor(config) {
|
|
32
|
+
if (!config.recipientAddress) {
|
|
33
|
+
throw new Error("recipientAddress is required");
|
|
34
|
+
}
|
|
35
|
+
this.config = {
|
|
36
|
+
recipientAddress: config.recipientAddress,
|
|
37
|
+
relayer: config.relayer || DEFAULT_RELAYER_ADDRESS,
|
|
38
|
+
waitUntil: config.waitUntil || "confirmed",
|
|
39
|
+
baseUrl: config.baseUrl || DEFAULT_FACILITATOR_URL,
|
|
40
|
+
apiKey: config.apiKey || ""
|
|
41
|
+
};
|
|
42
|
+
this.authHeaders = this.config.apiKey ? {
|
|
43
|
+
Authorization: `Bearer ${this.config.apiKey}`
|
|
44
|
+
} : {};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 获取 relayer 地址
|
|
48
|
+
*/
|
|
49
|
+
get relayer() {
|
|
50
|
+
return this.config.relayer;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 获取 recipient 地址
|
|
54
|
+
*/
|
|
55
|
+
get recipientAddress() {
|
|
56
|
+
return this.config.recipientAddress;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* 获取等待策略
|
|
60
|
+
*/
|
|
61
|
+
get waitUntil() {
|
|
62
|
+
return this.config.waitUntil;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 验证支付
|
|
66
|
+
* @param payload 支付负载
|
|
67
|
+
* @param requirements 支付要求
|
|
68
|
+
* @returns 验证结果
|
|
69
|
+
*/
|
|
70
|
+
async verify(payload, requirements) {
|
|
71
|
+
try {
|
|
72
|
+
const response = await fetch(`${this.config.baseUrl}/verify`, {
|
|
73
|
+
method: "POST",
|
|
74
|
+
headers: {
|
|
75
|
+
"Content-Type": "application/json",
|
|
76
|
+
...this.authHeaders
|
|
77
|
+
},
|
|
78
|
+
body: JSON.stringify({
|
|
79
|
+
x402Version: payload.x402Version,
|
|
80
|
+
paymentPayload: payload,
|
|
81
|
+
paymentRequirements: requirements
|
|
82
|
+
})
|
|
83
|
+
});
|
|
84
|
+
if (!response.ok) {
|
|
85
|
+
const errorText = await response.text();
|
|
86
|
+
return {
|
|
87
|
+
success: false,
|
|
88
|
+
error: `Verification failed: ${response.status}`,
|
|
89
|
+
errorMessage: errorText
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const data = await response.json();
|
|
93
|
+
return {
|
|
94
|
+
success: data.success ?? true,
|
|
95
|
+
payer: data.payer,
|
|
96
|
+
error: data.error,
|
|
97
|
+
errorMessage: data.errorMessage
|
|
98
|
+
};
|
|
99
|
+
} catch (error) {
|
|
100
|
+
return {
|
|
101
|
+
success: false,
|
|
102
|
+
error: "Verification error",
|
|
103
|
+
errorMessage: error instanceof Error ? error.message : "Unknown error"
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 结算支付
|
|
109
|
+
* @param payload 支付负载
|
|
110
|
+
* @param requirements 支付要求
|
|
111
|
+
* @param waitUntil 可选的等待策略,覆盖配置中的默认值
|
|
112
|
+
* @returns 结算结果
|
|
113
|
+
*/
|
|
114
|
+
async settle(payload, requirements, waitUntil) {
|
|
115
|
+
try {
|
|
116
|
+
const response = await fetch(`${this.config.baseUrl}/settle`, {
|
|
117
|
+
method: "POST",
|
|
118
|
+
headers: {
|
|
119
|
+
"Content-Type": "application/json",
|
|
120
|
+
...this.authHeaders
|
|
121
|
+
},
|
|
122
|
+
body: JSON.stringify({
|
|
123
|
+
x402Version: payload.x402Version,
|
|
124
|
+
paymentPayload: payload,
|
|
125
|
+
paymentRequirements: requirements,
|
|
126
|
+
waitUntil: waitUntil || this.config.waitUntil
|
|
127
|
+
})
|
|
128
|
+
});
|
|
129
|
+
if (!response.ok) {
|
|
130
|
+
const errorText = await response.text();
|
|
131
|
+
return {
|
|
132
|
+
success: false,
|
|
133
|
+
error: `Settlement failed: ${response.status}`,
|
|
134
|
+
errorMessage: errorText
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
const data = await response.json();
|
|
138
|
+
return {
|
|
139
|
+
success: data.success ?? true,
|
|
140
|
+
transactionHash: data.transactionHash,
|
|
141
|
+
network: data.network,
|
|
142
|
+
receipt: data.receipt,
|
|
143
|
+
error: data.error,
|
|
144
|
+
errorMessage: data.errorMessage
|
|
145
|
+
};
|
|
146
|
+
} catch (error) {
|
|
147
|
+
return {
|
|
148
|
+
success: false,
|
|
149
|
+
error: "Settlement error",
|
|
150
|
+
errorMessage: error instanceof Error ? error.message : "Unknown error"
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* 获取支持的支付类型
|
|
156
|
+
* @param filters 可选的过滤条件
|
|
157
|
+
* @returns 支持的支付类型列表
|
|
158
|
+
*/
|
|
159
|
+
async supported(filters) {
|
|
160
|
+
try {
|
|
161
|
+
const url = new URL(`${this.config.baseUrl}/supported`);
|
|
162
|
+
if (filters?.chainId) {
|
|
163
|
+
url.searchParams.set("chainId", filters.chainId.toString());
|
|
164
|
+
}
|
|
165
|
+
if (filters?.tokenAddress) {
|
|
166
|
+
url.searchParams.set("tokenAddress", filters.tokenAddress);
|
|
167
|
+
}
|
|
168
|
+
const response = await fetch(url.toString(), {
|
|
169
|
+
headers: this.authHeaders
|
|
170
|
+
});
|
|
171
|
+
if (!response.ok) {
|
|
172
|
+
throw new Error(`Failed to get supported kinds: ${response.status}`);
|
|
173
|
+
}
|
|
174
|
+
const data = await response.json();
|
|
175
|
+
return data;
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.error("Error fetching supported payment kinds:", error);
|
|
178
|
+
return { kinds: [] };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* 获取完整配置
|
|
183
|
+
*/
|
|
184
|
+
getConfig() {
|
|
185
|
+
return { ...this.config };
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
189
|
+
0 && (module.exports = {
|
|
190
|
+
Facilitator
|
|
191
|
+
});
|
|
192
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/facilitator.ts"],"sourcesContent":["export { Facilitator } from \"./facilitator\";\nexport * from \"./types\";\n\n","import type {\n FacilitatorConfig,\n PaymentPayload,\n PaymentRequirements,\n SettleResponse,\n SupportedResponse,\n VerifyResponse,\n WaitUntil,\n} from \"./types\";\n\n/**\n * WTF Facilitator 默认 URL\n */\nconst DEFAULT_FACILITATOR_URL = \"https://facilitator.wtf.com/v1\";\n\n/**\n * 默认 Relayer 地址\n */\nconst DEFAULT_RELAYER_ADDRESS = \"0x877D0A51a37178b5F34Ffb68a5c2beD0ff46D432\";\n\n/**\n * Facilitator 类\n * 用于处理支付验证和结算\n *\n * @example\n * ```typescript\n * const facilitator = new Facilitator({\n * recipientAddress: \"0x1234...\",\n * relayer: \"0x5678...\", // 可选\n * waitUntil: \"confirmed\", // 可选\n * });\n *\n * // 验证支付\n * const verifyResult = await facilitator.verify(\n * paymentPayload,\n * paymentRequirements\n * );\n *\n * // 结算支付\n * const settleResult = await facilitator.settle(\n * paymentPayload,\n * paymentRequirements\n * );\n *\n * // 获取支持的支付类型\n * const supported = await facilitator.supported();\n * ```\n */\nexport class Facilitator {\n private config: Required<FacilitatorConfig>;\n private authHeaders: Record<string, string>;\n\n constructor(config: FacilitatorConfig) {\n if (!config.recipientAddress) {\n throw new Error(\"recipientAddress is required\");\n }\n\n this.config = {\n recipientAddress: config.recipientAddress,\n relayer: config.relayer || DEFAULT_RELAYER_ADDRESS,\n waitUntil: config.waitUntil || \"confirmed\",\n baseUrl: config.baseUrl || DEFAULT_FACILITATOR_URL,\n apiKey: config.apiKey || \"\",\n };\n\n this.authHeaders = this.config.apiKey\n ? {\n Authorization: `Bearer ${this.config.apiKey}`,\n }\n : {};\n }\n\n /**\n * 获取 relayer 地址\n */\n get relayer(): string {\n return this.config.relayer;\n }\n\n /**\n * 获取 recipient 地址\n */\n get recipientAddress(): string {\n return this.config.recipientAddress;\n }\n\n /**\n * 获取等待策略\n */\n get waitUntil(): WaitUntil {\n return this.config.waitUntil;\n }\n\n /**\n * 验证支付\n * @param payload 支付负载\n * @param requirements 支付要求\n * @returns 验证结果\n */\n async verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n ): Promise<VerifyResponse> {\n try {\n const response = await fetch(`${this.config.baseUrl}/verify`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.authHeaders,\n },\n body: JSON.stringify({\n x402Version: payload.x402Version,\n paymentPayload: payload,\n paymentRequirements: requirements,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n return {\n success: false,\n error: `Verification failed: ${response.status}`,\n errorMessage: errorText,\n };\n }\n\n const data = (await response.json()) as {\n success?: boolean;\n payer?: string;\n error?: string;\n errorMessage?: string;\n };\n return {\n success: data.success ?? true,\n payer: data.payer,\n error: data.error,\n errorMessage: data.errorMessage,\n };\n } catch (error) {\n return {\n success: false,\n error: \"Verification error\",\n errorMessage:\n error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n }\n\n /**\n * 结算支付\n * @param payload 支付负载\n * @param requirements 支付要求\n * @param waitUntil 可选的等待策略,覆盖配置中的默认值\n * @returns 结算结果\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n waitUntil?: WaitUntil,\n ): Promise<SettleResponse> {\n try {\n const response = await fetch(`${this.config.baseUrl}/settle`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.authHeaders,\n },\n body: JSON.stringify({\n x402Version: payload.x402Version,\n paymentPayload: payload,\n paymentRequirements: requirements,\n waitUntil: waitUntil || this.config.waitUntil,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n return {\n success: false,\n error: `Settlement failed: ${response.status}`,\n errorMessage: errorText,\n };\n }\n\n const data = (await response.json()) as {\n success?: boolean;\n transactionHash?: string;\n network?: string;\n receipt?: any;\n error?: string;\n errorMessage?: string;\n };\n return {\n success: data.success ?? true,\n transactionHash: data.transactionHash,\n network: data.network,\n receipt: data.receipt,\n error: data.error,\n errorMessage: data.errorMessage,\n };\n } catch (error) {\n return {\n success: false,\n error: \"Settlement error\",\n errorMessage:\n error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n }\n\n /**\n * 获取支持的支付类型\n * @param filters 可选的过滤条件\n * @returns 支持的支付类型列表\n */\n async supported(filters?: {\n chainId?: number;\n tokenAddress?: string;\n }): Promise<SupportedResponse> {\n try {\n const url = new URL(`${this.config.baseUrl}/supported`);\n if (filters?.chainId) {\n url.searchParams.set(\"chainId\", filters.chainId.toString());\n }\n if (filters?.tokenAddress) {\n url.searchParams.set(\"tokenAddress\", filters.tokenAddress);\n }\n\n const response = await fetch(url.toString(), {\n headers: this.authHeaders,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to get supported kinds: ${response.status}`);\n }\n\n const data = await response.json();\n return data as SupportedResponse;\n } catch (error) {\n console.error(\"Error fetching supported payment kinds:\", error);\n return { kinds: [] };\n }\n }\n\n /**\n * 获取完整配置\n */\n getConfig(): Required<FacilitatorConfig> {\n return { ...this.config };\n }\n}\n\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// src/facilitator.ts
|
|
2
|
+
var DEFAULT_FACILITATOR_URL = "https://facilitator.wtf.com/v1";
|
|
3
|
+
var DEFAULT_RELAYER_ADDRESS = "0x877D0A51a37178b5F34Ffb68a5c2beD0ff46D432";
|
|
4
|
+
var Facilitator = class {
|
|
5
|
+
constructor(config) {
|
|
6
|
+
if (!config.recipientAddress) {
|
|
7
|
+
throw new Error("recipientAddress is required");
|
|
8
|
+
}
|
|
9
|
+
this.config = {
|
|
10
|
+
recipientAddress: config.recipientAddress,
|
|
11
|
+
relayer: config.relayer || DEFAULT_RELAYER_ADDRESS,
|
|
12
|
+
waitUntil: config.waitUntil || "confirmed",
|
|
13
|
+
baseUrl: config.baseUrl || DEFAULT_FACILITATOR_URL,
|
|
14
|
+
apiKey: config.apiKey || ""
|
|
15
|
+
};
|
|
16
|
+
this.authHeaders = this.config.apiKey ? {
|
|
17
|
+
Authorization: `Bearer ${this.config.apiKey}`
|
|
18
|
+
} : {};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 获取 relayer 地址
|
|
22
|
+
*/
|
|
23
|
+
get relayer() {
|
|
24
|
+
return this.config.relayer;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 获取 recipient 地址
|
|
28
|
+
*/
|
|
29
|
+
get recipientAddress() {
|
|
30
|
+
return this.config.recipientAddress;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 获取等待策略
|
|
34
|
+
*/
|
|
35
|
+
get waitUntil() {
|
|
36
|
+
return this.config.waitUntil;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 验证支付
|
|
40
|
+
* @param payload 支付负载
|
|
41
|
+
* @param requirements 支付要求
|
|
42
|
+
* @returns 验证结果
|
|
43
|
+
*/
|
|
44
|
+
async verify(payload, requirements) {
|
|
45
|
+
try {
|
|
46
|
+
const response = await fetch(`${this.config.baseUrl}/verify`, {
|
|
47
|
+
method: "POST",
|
|
48
|
+
headers: {
|
|
49
|
+
"Content-Type": "application/json",
|
|
50
|
+
...this.authHeaders
|
|
51
|
+
},
|
|
52
|
+
body: JSON.stringify({
|
|
53
|
+
x402Version: payload.x402Version,
|
|
54
|
+
paymentPayload: payload,
|
|
55
|
+
paymentRequirements: requirements
|
|
56
|
+
})
|
|
57
|
+
});
|
|
58
|
+
if (!response.ok) {
|
|
59
|
+
const errorText = await response.text();
|
|
60
|
+
return {
|
|
61
|
+
success: false,
|
|
62
|
+
error: `Verification failed: ${response.status}`,
|
|
63
|
+
errorMessage: errorText
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const data = await response.json();
|
|
67
|
+
return {
|
|
68
|
+
success: data.success ?? true,
|
|
69
|
+
payer: data.payer,
|
|
70
|
+
error: data.error,
|
|
71
|
+
errorMessage: data.errorMessage
|
|
72
|
+
};
|
|
73
|
+
} catch (error) {
|
|
74
|
+
return {
|
|
75
|
+
success: false,
|
|
76
|
+
error: "Verification error",
|
|
77
|
+
errorMessage: error instanceof Error ? error.message : "Unknown error"
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 结算支付
|
|
83
|
+
* @param payload 支付负载
|
|
84
|
+
* @param requirements 支付要求
|
|
85
|
+
* @param waitUntil 可选的等待策略,覆盖配置中的默认值
|
|
86
|
+
* @returns 结算结果
|
|
87
|
+
*/
|
|
88
|
+
async settle(payload, requirements, waitUntil) {
|
|
89
|
+
try {
|
|
90
|
+
const response = await fetch(`${this.config.baseUrl}/settle`, {
|
|
91
|
+
method: "POST",
|
|
92
|
+
headers: {
|
|
93
|
+
"Content-Type": "application/json",
|
|
94
|
+
...this.authHeaders
|
|
95
|
+
},
|
|
96
|
+
body: JSON.stringify({
|
|
97
|
+
x402Version: payload.x402Version,
|
|
98
|
+
paymentPayload: payload,
|
|
99
|
+
paymentRequirements: requirements,
|
|
100
|
+
waitUntil: waitUntil || this.config.waitUntil
|
|
101
|
+
})
|
|
102
|
+
});
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
const errorText = await response.text();
|
|
105
|
+
return {
|
|
106
|
+
success: false,
|
|
107
|
+
error: `Settlement failed: ${response.status}`,
|
|
108
|
+
errorMessage: errorText
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const data = await response.json();
|
|
112
|
+
return {
|
|
113
|
+
success: data.success ?? true,
|
|
114
|
+
transactionHash: data.transactionHash,
|
|
115
|
+
network: data.network,
|
|
116
|
+
receipt: data.receipt,
|
|
117
|
+
error: data.error,
|
|
118
|
+
errorMessage: data.errorMessage
|
|
119
|
+
};
|
|
120
|
+
} catch (error) {
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
error: "Settlement error",
|
|
124
|
+
errorMessage: error instanceof Error ? error.message : "Unknown error"
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 获取支持的支付类型
|
|
130
|
+
* @param filters 可选的过滤条件
|
|
131
|
+
* @returns 支持的支付类型列表
|
|
132
|
+
*/
|
|
133
|
+
async supported(filters) {
|
|
134
|
+
try {
|
|
135
|
+
const url = new URL(`${this.config.baseUrl}/supported`);
|
|
136
|
+
if (filters?.chainId) {
|
|
137
|
+
url.searchParams.set("chainId", filters.chainId.toString());
|
|
138
|
+
}
|
|
139
|
+
if (filters?.tokenAddress) {
|
|
140
|
+
url.searchParams.set("tokenAddress", filters.tokenAddress);
|
|
141
|
+
}
|
|
142
|
+
const response = await fetch(url.toString(), {
|
|
143
|
+
headers: this.authHeaders
|
|
144
|
+
});
|
|
145
|
+
if (!response.ok) {
|
|
146
|
+
throw new Error(`Failed to get supported kinds: ${response.status}`);
|
|
147
|
+
}
|
|
148
|
+
const data = await response.json();
|
|
149
|
+
return data;
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error("Error fetching supported payment kinds:", error);
|
|
152
|
+
return { kinds: [] };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* 获取完整配置
|
|
157
|
+
*/
|
|
158
|
+
getConfig() {
|
|
159
|
+
return { ...this.config };
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
export {
|
|
163
|
+
Facilitator
|
|
164
|
+
};
|
|
165
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/facilitator.ts"],"sourcesContent":["import type {\n FacilitatorConfig,\n PaymentPayload,\n PaymentRequirements,\n SettleResponse,\n SupportedResponse,\n VerifyResponse,\n WaitUntil,\n} from \"./types\";\n\n/**\n * WTF Facilitator 默认 URL\n */\nconst DEFAULT_FACILITATOR_URL = \"https://facilitator.wtf.com/v1\";\n\n/**\n * 默认 Relayer 地址\n */\nconst DEFAULT_RELAYER_ADDRESS = \"0x877D0A51a37178b5F34Ffb68a5c2beD0ff46D432\";\n\n/**\n * Facilitator 类\n * 用于处理支付验证和结算\n *\n * @example\n * ```typescript\n * const facilitator = new Facilitator({\n * recipientAddress: \"0x1234...\",\n * relayer: \"0x5678...\", // 可选\n * waitUntil: \"confirmed\", // 可选\n * });\n *\n * // 验证支付\n * const verifyResult = await facilitator.verify(\n * paymentPayload,\n * paymentRequirements\n * );\n *\n * // 结算支付\n * const settleResult = await facilitator.settle(\n * paymentPayload,\n * paymentRequirements\n * );\n *\n * // 获取支持的支付类型\n * const supported = await facilitator.supported();\n * ```\n */\nexport class Facilitator {\n private config: Required<FacilitatorConfig>;\n private authHeaders: Record<string, string>;\n\n constructor(config: FacilitatorConfig) {\n if (!config.recipientAddress) {\n throw new Error(\"recipientAddress is required\");\n }\n\n this.config = {\n recipientAddress: config.recipientAddress,\n relayer: config.relayer || DEFAULT_RELAYER_ADDRESS,\n waitUntil: config.waitUntil || \"confirmed\",\n baseUrl: config.baseUrl || DEFAULT_FACILITATOR_URL,\n apiKey: config.apiKey || \"\",\n };\n\n this.authHeaders = this.config.apiKey\n ? {\n Authorization: `Bearer ${this.config.apiKey}`,\n }\n : {};\n }\n\n /**\n * 获取 relayer 地址\n */\n get relayer(): string {\n return this.config.relayer;\n }\n\n /**\n * 获取 recipient 地址\n */\n get recipientAddress(): string {\n return this.config.recipientAddress;\n }\n\n /**\n * 获取等待策略\n */\n get waitUntil(): WaitUntil {\n return this.config.waitUntil;\n }\n\n /**\n * 验证支付\n * @param payload 支付负载\n * @param requirements 支付要求\n * @returns 验证结果\n */\n async verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n ): Promise<VerifyResponse> {\n try {\n const response = await fetch(`${this.config.baseUrl}/verify`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.authHeaders,\n },\n body: JSON.stringify({\n x402Version: payload.x402Version,\n paymentPayload: payload,\n paymentRequirements: requirements,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n return {\n success: false,\n error: `Verification failed: ${response.status}`,\n errorMessage: errorText,\n };\n }\n\n const data = (await response.json()) as {\n success?: boolean;\n payer?: string;\n error?: string;\n errorMessage?: string;\n };\n return {\n success: data.success ?? true,\n payer: data.payer,\n error: data.error,\n errorMessage: data.errorMessage,\n };\n } catch (error) {\n return {\n success: false,\n error: \"Verification error\",\n errorMessage:\n error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n }\n\n /**\n * 结算支付\n * @param payload 支付负载\n * @param requirements 支付要求\n * @param waitUntil 可选的等待策略,覆盖配置中的默认值\n * @returns 结算结果\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n waitUntil?: WaitUntil,\n ): Promise<SettleResponse> {\n try {\n const response = await fetch(`${this.config.baseUrl}/settle`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...this.authHeaders,\n },\n body: JSON.stringify({\n x402Version: payload.x402Version,\n paymentPayload: payload,\n paymentRequirements: requirements,\n waitUntil: waitUntil || this.config.waitUntil,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n return {\n success: false,\n error: `Settlement failed: ${response.status}`,\n errorMessage: errorText,\n };\n }\n\n const data = (await response.json()) as {\n success?: boolean;\n transactionHash?: string;\n network?: string;\n receipt?: any;\n error?: string;\n errorMessage?: string;\n };\n return {\n success: data.success ?? true,\n transactionHash: data.transactionHash,\n network: data.network,\n receipt: data.receipt,\n error: data.error,\n errorMessage: data.errorMessage,\n };\n } catch (error) {\n return {\n success: false,\n error: \"Settlement error\",\n errorMessage:\n error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n }\n\n /**\n * 获取支持的支付类型\n * @param filters 可选的过滤条件\n * @returns 支持的支付类型列表\n */\n async supported(filters?: {\n chainId?: number;\n tokenAddress?: string;\n }): Promise<SupportedResponse> {\n try {\n const url = new URL(`${this.config.baseUrl}/supported`);\n if (filters?.chainId) {\n url.searchParams.set(\"chainId\", filters.chainId.toString());\n }\n if (filters?.tokenAddress) {\n url.searchParams.set(\"tokenAddress\", filters.tokenAddress);\n }\n\n const response = await fetch(url.toString(), {\n headers: this.authHeaders,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to get supported kinds: ${response.status}`);\n }\n\n const data = await response.json();\n return data as SupportedResponse;\n } catch (error) {\n console.error(\"Error fetching supported payment kinds:\", error);\n return { kinds: [] };\n }\n }\n\n /**\n * 获取完整配置\n */\n getConfig(): Required<FacilitatorConfig> {\n return { ...this.config };\n }\n}\n\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wtflabs/x402-facilitator",
|
|
3
|
+
"version": "0.0.1-beta.2",
|
|
4
|
+
"main": "./dist/index.js",
|
|
5
|
+
"module": "./dist/index.mjs",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"x402",
|
|
9
|
+
"payment",
|
|
10
|
+
"facilitator"
|
|
11
|
+
],
|
|
12
|
+
"license": "Apache-2.0",
|
|
13
|
+
"description": "X402 Payment Facilitator for handling payment settlements",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/node": "^22.13.4",
|
|
16
|
+
"tsup": "^8.4.0",
|
|
17
|
+
"tsx": "^4.19.2",
|
|
18
|
+
"typescript": "^5.7.3",
|
|
19
|
+
"vitest": "^3.0.5"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@wtflabs/x402": "^0.0.1-beta.4"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"import": {
|
|
27
|
+
"types": "./dist/index.d.mts",
|
|
28
|
+
"default": "./dist/index.mjs"
|
|
29
|
+
},
|
|
30
|
+
"require": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"default": "./dist/index.js"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"test:watch": "vitest",
|
|
43
|
+
"watch": "tsc --watch",
|
|
44
|
+
"format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"",
|
|
45
|
+
"format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"",
|
|
46
|
+
"lint": "eslint . --ext .ts --fix",
|
|
47
|
+
"lint:check": "eslint . --ext .ts"
|
|
48
|
+
}
|
|
49
|
+
}
|