@x402r/evm 0.0.2 → 0.0.3

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.
Files changed (89) hide show
  1. package/README.md +20 -16
  2. package/dist/cjs/escrow/client/index.cjs +227 -0
  3. package/dist/cjs/escrow/client/index.cjs.map +1 -0
  4. package/dist/cjs/escrow/client/index.d.cts +23 -0
  5. package/dist/cjs/escrow/client/index.d.ts +23 -0
  6. package/dist/cjs/escrow/client/index.js +223 -0
  7. package/dist/cjs/escrow/client/index.js.map +1 -0
  8. package/dist/cjs/escrow/facilitator/index.cjs +359 -0
  9. package/dist/cjs/escrow/facilitator/index.cjs.map +1 -0
  10. package/dist/cjs/escrow/facilitator/index.d.cts +53 -0
  11. package/dist/{escrow → cjs/escrow}/facilitator/index.d.ts +17 -13
  12. package/dist/cjs/escrow/facilitator/index.js +358 -0
  13. package/dist/cjs/escrow/facilitator/index.js.map +1 -0
  14. package/dist/cjs/escrow/server/index.cjs +222 -0
  15. package/dist/cjs/escrow/server/index.cjs.map +1 -0
  16. package/dist/cjs/escrow/server/index.d.cts +78 -0
  17. package/dist/{escrow → cjs/escrow}/server/index.d.ts +15 -9
  18. package/dist/cjs/escrow/server/index.js +217 -0
  19. package/dist/cjs/escrow/server/index.js.map +1 -0
  20. package/dist/{shared/types.d.ts → cjs/escrow/types/index.d.ts} +7 -6
  21. package/dist/cjs/escrow/types/index.js +40 -0
  22. package/dist/cjs/escrow/types/index.js.map +1 -0
  23. package/dist/cjs/index.cjs +215 -0
  24. package/dist/cjs/index.cjs.map +1 -0
  25. package/dist/cjs/index.d.cts +22 -0
  26. package/dist/cjs/index.d.ts +54 -0
  27. package/dist/cjs/index.js +223 -0
  28. package/dist/cjs/index.js.map +1 -0
  29. package/dist/cjs/scheme-CNrmuyp3.d.ts +22 -0
  30. package/dist/esm/chunk-DLIBGHEY.mjs +85 -0
  31. package/dist/esm/chunk-DLIBGHEY.mjs.map +1 -0
  32. package/dist/esm/chunk-IYUU7AJZ.mjs +187 -0
  33. package/dist/esm/chunk-IYUU7AJZ.mjs.map +1 -0
  34. package/dist/esm/chunk-JBHVAJN3.mjs +13 -0
  35. package/dist/esm/chunk-JBHVAJN3.mjs.map +1 -0
  36. package/dist/esm/chunk-NSSMTXJJ.mjs +8 -0
  37. package/dist/esm/chunk-NSSMTXJJ.mjs.map +1 -0
  38. package/dist/esm/escrow/client/index.d.mts +23 -0
  39. package/dist/esm/escrow/client/index.mjs +20 -0
  40. package/dist/esm/escrow/client/index.mjs.map +1 -0
  41. package/dist/esm/escrow/facilitator/index.d.mts +53 -0
  42. package/dist/esm/escrow/facilitator/index.mjs +230 -0
  43. package/dist/esm/escrow/facilitator/index.mjs.map +1 -0
  44. package/dist/esm/escrow/server/index.d.mts +78 -0
  45. package/dist/esm/escrow/server/index.mjs +191 -0
  46. package/dist/esm/escrow/server/index.mjs.map +1 -0
  47. package/dist/esm/index.d.mts +54 -0
  48. package/dist/esm/index.mjs +15 -0
  49. package/dist/esm/index.mjs.map +1 -0
  50. package/dist/esm/scheme-CNrmuyp3.d.mts +22 -0
  51. package/package.json +42 -16
  52. package/src/escrow/client/index.ts +3 -161
  53. package/src/escrow/client/register.ts +33 -0
  54. package/src/escrow/client/scheme.ts +107 -0
  55. package/src/escrow/facilitator/index.ts +3 -388
  56. package/src/escrow/facilitator/register.ts +33 -0
  57. package/src/escrow/facilitator/scheme.ts +289 -0
  58. package/src/escrow/index.ts +3 -0
  59. package/src/escrow/server/index.ts +3 -261
  60. package/src/escrow/server/register.ts +34 -0
  61. package/src/escrow/server/scheme.ts +226 -0
  62. package/src/escrow/shared/constants.ts +65 -0
  63. package/src/escrow/shared/nonce.ts +175 -0
  64. package/src/escrow/shared/types.ts +69 -0
  65. package/src/escrow/shared/utils.ts +16 -0
  66. package/dist/escrow/client/index.d.ts +0 -40
  67. package/dist/escrow/client/index.d.ts.map +0 -1
  68. package/dist/escrow/client/index.js +0 -104
  69. package/dist/escrow/client/index.js.map +0 -1
  70. package/dist/escrow/facilitator/index.d.ts.map +0 -1
  71. package/dist/escrow/facilitator/index.js +0 -300
  72. package/dist/escrow/facilitator/index.js.map +0 -1
  73. package/dist/escrow/server/index.d.ts.map +0 -1
  74. package/dist/escrow/server/index.js +0 -214
  75. package/dist/escrow/server/index.js.map +0 -1
  76. package/dist/shared/constants.d.ts +0 -112
  77. package/dist/shared/constants.d.ts.map +0 -1
  78. package/dist/shared/constants.js +0 -51
  79. package/dist/shared/constants.js.map +0 -1
  80. package/dist/shared/nonce.d.ts +0 -41
  81. package/dist/shared/nonce.d.ts.map +0 -1
  82. package/dist/shared/nonce.js +0 -154
  83. package/dist/shared/nonce.js.map +0 -1
  84. package/dist/shared/types.d.ts.map +0 -1
  85. package/dist/shared/types.js +0 -21
  86. package/dist/shared/types.js.map +0 -1
  87. package/src/shared/constants.ts +0 -58
  88. package/src/shared/nonce.ts +0 -203
  89. package/src/shared/types.ts +0 -69
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Escrow Scheme - Facilitator
3
+ * Handles verification and settlement of escrow payments.
4
+ *
5
+ * Implements x402's SchemeNetworkFacilitator interface so the escrow scheme
6
+ * is a drop-in for the x402 facilitator, just like ExactEvmScheme.
7
+ */
8
+
9
+ import type {
10
+ FacilitatorContext,
11
+ PaymentPayload,
12
+ PaymentRequirements,
13
+ SchemeNetworkFacilitator,
14
+ SettleResponse,
15
+ VerifyResponse,
16
+ } from '@x402/core/types'
17
+ import type { FacilitatorEvmSigner } from '@x402/evm'
18
+ import { parseErc6492Signature } from 'viem'
19
+ import { OPERATOR_ABI, ERC20_BALANCE_OF_ABI } from '../shared/constants'
20
+ import { verifyERC3009Signature } from '../shared/nonce'
21
+ import { isEscrowPayload, isEscrowExtra } from '../shared/types'
22
+ import type { EscrowExtra, EscrowPayload } from '../shared/types'
23
+ import { parseChainId } from '../shared/utils'
24
+
25
+ /**
26
+ * Escrow Facilitator Scheme - implements x402's SchemeNetworkFacilitator
27
+ *
28
+ * The facilitator is operator-agnostic: it does not store operator/escrow/tokenCollector
29
+ * config. Those values are set by the merchant via `refundable()` and arrive in
30
+ * `requirements.extra` at verify/settle time.
31
+ */
32
+ export class EscrowFacilitatorScheme implements SchemeNetworkFacilitator {
33
+ readonly scheme = 'escrow'
34
+ readonly caipFamily = 'eip155:*'
35
+
36
+ constructor(private signer: FacilitatorEvmSigner) {}
37
+
38
+ getSigners(_network: string): string[] {
39
+ return [...this.signer.getAddresses()]
40
+ }
41
+
42
+ // C4: name/version now come from server's parsePrice() via AssetAmount.extra.
43
+ // The facilitator should not hardcode token-specific metadata.
44
+ getExtra(_network: string): Record<string, unknown> | undefined {
45
+ return undefined
46
+ }
47
+
48
+ async verify(
49
+ payload: PaymentPayload,
50
+ requirements: PaymentRequirements,
51
+ _context?: FacilitatorContext,
52
+ ): Promise<VerifyResponse> {
53
+ // M5: Type guard instead of double cast
54
+ if (!isEscrowPayload(payload.payload)) {
55
+ return {
56
+ isValid: false,
57
+ invalidReason: 'invalid_payload_format',
58
+ }
59
+ }
60
+ const escrowPayload = payload.payload as EscrowPayload
61
+ const payer = escrowPayload.authorization.from
62
+
63
+ // Validate scheme on both payload and requirements
64
+ if (payload.accepted.scheme !== 'escrow' || requirements.scheme !== 'escrow') {
65
+ return {
66
+ isValid: false,
67
+ invalidReason: 'unsupported_scheme',
68
+ payer,
69
+ }
70
+ }
71
+
72
+ // Validate network matches between payload and requirements
73
+ if (payload.accepted.network !== requirements.network) {
74
+ return {
75
+ isValid: false,
76
+ invalidReason: 'network_mismatch',
77
+ payer,
78
+ }
79
+ }
80
+
81
+ // Validate network format
82
+ const networkParts = requirements.network.split(':')
83
+ if (networkParts.length !== 2 || networkParts[0] !== 'eip155') {
84
+ return {
85
+ isValid: false,
86
+ invalidReason: 'invalid_network',
87
+ payer,
88
+ }
89
+ }
90
+
91
+ // M5: Type guard for extra
92
+ if (!isEscrowExtra(requirements.extra)) {
93
+ return {
94
+ isValid: false,
95
+ invalidReason: 'invalid_escrow_extra',
96
+ payer,
97
+ }
98
+ }
99
+ const extra = requirements.extra as EscrowExtra
100
+ const chainId = parseChainId(requirements.network)
101
+
102
+ // Time window validation
103
+ const now = Math.floor(Date.now() / 1000)
104
+ const validBefore = Number(escrowPayload.authorization.validBefore)
105
+ const validAfter = Number(escrowPayload.authorization.validAfter)
106
+
107
+ if (validBefore <= now + 6) {
108
+ return {
109
+ isValid: false,
110
+ invalidReason: 'authorization_expired',
111
+ payer,
112
+ }
113
+ }
114
+
115
+ if (validAfter > now) {
116
+ return {
117
+ isValid: false,
118
+ invalidReason: 'authorization_not_yet_valid',
119
+ payer,
120
+ }
121
+ }
122
+
123
+ // Extract inner signature for verification if EIP-6492 wrapped.
124
+ // The contract's ERC6492SignatureHandler handles deployment; the facilitator
125
+ // only needs the inner ECDSA signature for ecrecover verification.
126
+ const { signature: signatureForVerify } = parseErc6492Signature(escrowPayload.signature)
127
+
128
+ // Verify ERC-3009 signature
129
+ const isValidSignature = await verifyERC3009Signature(
130
+ this.signer,
131
+ escrowPayload.authorization,
132
+ signatureForVerify,
133
+ { ...extra, chainId },
134
+ requirements.asset as `0x${string}`,
135
+ )
136
+
137
+ if (!isValidSignature) {
138
+ return {
139
+ isValid: false,
140
+ invalidReason: 'invalid_escrow_signature',
141
+ payer,
142
+ }
143
+ }
144
+
145
+ // Verify amount meets requirements
146
+ if (BigInt(escrowPayload.authorization.value) < BigInt(requirements.amount)) {
147
+ return {
148
+ isValid: false,
149
+ invalidReason: 'insufficient_amount',
150
+ payer,
151
+ }
152
+ }
153
+
154
+ // Verify token matches
155
+ if (escrowPayload.paymentInfo.token.toLowerCase() !== requirements.asset.toLowerCase()) {
156
+ return {
157
+ isValid: false,
158
+ invalidReason: 'token_mismatch',
159
+ payer,
160
+ }
161
+ }
162
+
163
+ // Verify receiver matches
164
+ if (escrowPayload.paymentInfo.receiver.toLowerCase() !== requirements.payTo.toLowerCase()) {
165
+ return {
166
+ isValid: false,
167
+ invalidReason: 'receiver_mismatch',
168
+ payer,
169
+ }
170
+ }
171
+
172
+ // H4: Balance check — verify payer has sufficient token balance
173
+ try {
174
+ const balance = await this.signer.readContract({
175
+ address: requirements.asset as `0x${string}`,
176
+ abi: ERC20_BALANCE_OF_ABI,
177
+ functionName: 'balanceOf',
178
+ args: [payer],
179
+ })
180
+
181
+ if (BigInt(balance as string) < BigInt(requirements.amount)) {
182
+ return {
183
+ isValid: false,
184
+ invalidReason: 'insufficient_balance',
185
+ payer,
186
+ }
187
+ }
188
+ } catch {
189
+ // If balance check fails (e.g., non-standard token), skip it.
190
+ // The on-chain transaction will fail anyway if balance is insufficient.
191
+ }
192
+
193
+ return {
194
+ isValid: true,
195
+ payer,
196
+ }
197
+ }
198
+
199
+ async settle(
200
+ payload: PaymentPayload,
201
+ requirements: PaymentRequirements,
202
+ _context?: FacilitatorContext,
203
+ ): Promise<SettleResponse> {
204
+ // H2: Re-verify before settling to catch expired/invalid payloads
205
+ const verification = await this.verify(payload, requirements)
206
+ if (!verification.isValid) {
207
+ return {
208
+ success: false,
209
+ errorReason: verification.invalidReason ?? 'verification_failed',
210
+ transaction: '',
211
+ network: requirements.network,
212
+ payer: verification.payer,
213
+ }
214
+ }
215
+
216
+ const escrowPayload = payload.payload as unknown as EscrowPayload
217
+ const extra = requirements.extra as unknown as EscrowExtra
218
+ const { authorizeAddress, operatorAddress, tokenCollector } = extra
219
+
220
+ const paymentInfo = {
221
+ operator: escrowPayload.paymentInfo.operator,
222
+ payer: escrowPayload.authorization.from,
223
+ receiver: escrowPayload.paymentInfo.receiver,
224
+ token: escrowPayload.paymentInfo.token,
225
+ maxAmount: BigInt(escrowPayload.paymentInfo.maxAmount),
226
+ preApprovalExpiry: escrowPayload.paymentInfo.preApprovalExpiry,
227
+ authorizationExpiry: escrowPayload.paymentInfo.authorizationExpiry,
228
+ refundExpiry: escrowPayload.paymentInfo.refundExpiry,
229
+ minFeeBps: escrowPayload.paymentInfo.minFeeBps,
230
+ maxFeeBps: escrowPayload.paymentInfo.maxFeeBps,
231
+ feeReceiver: escrowPayload.paymentInfo.feeReceiver,
232
+ salt: BigInt(escrowPayload.paymentInfo.salt),
233
+ }
234
+
235
+ // Pass raw signature — ERC3009PaymentCollector/ERC6492SignatureHandler
236
+ // handles EIP-6492 unwrapping and wallet deployment on-chain
237
+ const collectorData = escrowPayload.signature
238
+
239
+ const target = authorizeAddress ?? operatorAddress
240
+
241
+ try {
242
+ const txHash = await this.signer.writeContract({
243
+ address: target,
244
+ abi: OPERATOR_ABI,
245
+ functionName: 'authorize',
246
+ args: [
247
+ paymentInfo,
248
+ BigInt(escrowPayload.authorization.value),
249
+ tokenCollector,
250
+ collectorData,
251
+ ],
252
+ })
253
+
254
+ // Wait for transaction confirmation with 60s timeout to avoid hanging on stuck txs
255
+ const receiptPromise = this.signer.waitForTransactionReceipt({
256
+ hash: txHash,
257
+ })
258
+ const timeoutPromise = new Promise<never>((_, reject) =>
259
+ setTimeout(() => reject(new Error('Transaction receipt timeout after 60s')), 60_000),
260
+ )
261
+ const receipt = await Promise.race([receiptPromise, timeoutPromise])
262
+
263
+ if (receipt.status !== 'success') {
264
+ return {
265
+ success: false,
266
+ errorReason: 'transaction_reverted',
267
+ transaction: txHash,
268
+ network: requirements.network,
269
+ payer: escrowPayload.authorization.from,
270
+ }
271
+ }
272
+
273
+ return {
274
+ success: true,
275
+ transaction: txHash,
276
+ network: requirements.network,
277
+ payer: escrowPayload.authorization.from,
278
+ }
279
+ } catch (error) {
280
+ return {
281
+ success: false,
282
+ errorReason: error instanceof Error ? error.message : 'Settlement failed',
283
+ transaction: '',
284
+ network: requirements.network,
285
+ payer: escrowPayload.authorization.from,
286
+ }
287
+ }
288
+ }
289
+ }
@@ -0,0 +1,3 @@
1
+ export { EscrowEvmScheme } from './client/scheme'
2
+ export type { EscrowPayload, EscrowExtra } from './shared/types'
3
+ export { isEscrowPayload, isEscrowExtra } from './shared/types'
@@ -1,261 +1,3 @@
1
- /**
2
- * Escrow Scheme - Server
3
- * Handles price parsing and requirement enhancement for resource servers.
4
- *
5
- * Implements x402's SchemeNetworkServer interface so it can be registered
6
- * on an x402ResourceServer via server.register('eip155:84532', new EscrowServerScheme()).
7
- */
8
-
9
- import type {
10
- AssetAmount,
11
- MoneyParser,
12
- Network,
13
- PaymentRequirements,
14
- Price,
15
- SchemeNetworkServer,
16
- } from "@x402/core/types";
17
- import { x402ResourceServer } from "@x402/core/server";
18
-
19
- /**
20
- * Asset info including EIP-712 domain parameters per network
21
- */
22
- const ASSET_INFO: Record<
23
- string,
24
- { address: string; name: string; version: string; decimals: number }
25
- > = {
26
- // Base Sepolia
27
- "eip155:84532": {
28
- address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
29
- name: "USDC",
30
- version: "2",
31
- decimals: 6,
32
- },
33
- // Base mainnet
34
- "eip155:8453": {
35
- address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
36
- name: "USD Coin",
37
- version: "2",
38
- decimals: 6,
39
- },
40
- // Ethereum Sepolia
41
- "eip155:11155111": {
42
- address: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
43
- name: "USDC",
44
- version: "2",
45
- decimals: 6,
46
- },
47
- // Ethereum mainnet
48
- "eip155:1": {
49
- address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
50
- name: "USD Coin",
51
- version: "2",
52
- decimals: 6,
53
- },
54
- // Polygon
55
- "eip155:137": {
56
- address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
57
- name: "USD Coin",
58
- version: "2",
59
- decimals: 6,
60
- },
61
- // Arbitrum
62
- "eip155:42161": {
63
- address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
64
- name: "USD Coin",
65
- version: "2",
66
- decimals: 6,
67
- },
68
- // Celo
69
- "eip155:42220": {
70
- address: "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
71
- name: "USD Coin",
72
- version: "2",
73
- decimals: 6,
74
- },
75
- // Monad
76
- "eip155:143": {
77
- address: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
78
- name: "USDC",
79
- version: "2",
80
- decimals: 6,
81
- },
82
- // Avalanche
83
- "eip155:43114": {
84
- address: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
85
- name: "USD Coin",
86
- version: "2",
87
- decimals: 6,
88
- },
89
- };
90
-
91
- /**
92
- * Convert decimal amount to token units using string-based conversion
93
- * (e.g., 0.10 -> 100000 for 6-decimal tokens)
94
- * Avoids floating-point precision issues from BigInt(Math.round(...))
95
- */
96
- function convertToTokenAmount(decimalAmount: string, decimals: number): string {
97
- const amount = parseFloat(decimalAmount);
98
- if (isNaN(amount)) {
99
- throw new Error(`Invalid amount: ${decimalAmount}`);
100
- }
101
- const [intPart, decPart = ""] = String(amount).split(".");
102
- const paddedDec = decPart.padEnd(decimals, "0").slice(0, decimals);
103
- const tokenAmount = (intPart + paddedDec).replace(/^0+/, "") || "0";
104
- return tokenAmount;
105
- }
106
-
107
- /**
108
- * Server scheme - handles price parsing and requirement enhancement.
109
- * Implements x402's SchemeNetworkServer interface.
110
- */
111
- export class EscrowServerScheme implements SchemeNetworkServer {
112
- readonly scheme = "escrow";
113
- private moneyParsers: MoneyParser[] = [];
114
-
115
- /**
116
- * Register a custom money parser in the parser chain.
117
- * Multiple parsers can be registered — they will be tried in registration order.
118
- * Each parser receives a decimal amount (e.g., 1.50 for $1.50).
119
- * If a parser returns null, the next parser in the chain will be tried.
120
- * The default parser (USDC) is always the final fallback.
121
- *
122
- * @param parser - Custom function to convert amount to AssetAmount (or null to skip)
123
- * @returns The server instance for chaining
124
- */
125
- registerMoneyParser(parser: MoneyParser): EscrowServerScheme {
126
- this.moneyParsers.push(parser);
127
- return this;
128
- }
129
-
130
- /**
131
- * Parse a price into an x402 AssetAmount.
132
- *
133
- * Accepts x402's Price type:
134
- * - string: "$0.01", "0.01", "10000"
135
- * - number: 0.01
136
- * - AssetAmount: { asset: "0x...", amount: "10000" }
137
- */
138
- async parsePrice(price: Price, network: Network): Promise<AssetAmount> {
139
- // If already an AssetAmount, pass through with validation
140
- if (
141
- typeof price === "object" &&
142
- price !== null &&
143
- "amount" in price
144
- ) {
145
- if (!price.asset) {
146
- throw new Error(
147
- `Asset address must be specified for AssetAmount on network ${network}`,
148
- );
149
- }
150
- return {
151
- amount: price.amount,
152
- asset: price.asset,
153
- extra: price.extra || {},
154
- };
155
- }
156
-
157
- // Parse Money to decimal number
158
- const numericAmount = this.parseMoneyToDecimal(price);
159
-
160
- // Try each custom money parser in order
161
- for (const parser of this.moneyParsers) {
162
- const result = await parser(numericAmount, network);
163
- if (result !== null) {
164
- return result;
165
- }
166
- }
167
-
168
- // All custom parsers returned null (or none registered), use default conversion
169
- return this.defaultMoneyConversion(numericAmount, network);
170
- }
171
-
172
- /**
173
- * Parse Money (string | number) to a decimal number.
174
- */
175
- private parseMoneyToDecimal(money: string | number): number {
176
- if (typeof money === "number") {
177
- return money;
178
- }
179
- const cleaned = String(money).replace(/[$,]/g, "").trim();
180
- const amount = parseFloat(cleaned);
181
- if (isNaN(amount)) {
182
- throw new Error(`Cannot parse price: ${money}`);
183
- }
184
- return amount;
185
- }
186
-
187
- /**
188
- * Default money conversion — converts decimal amount to the default stablecoin on the network.
189
- */
190
- private defaultMoneyConversion(amount: number, network: Network): AssetAmount {
191
- const assetInfo = ASSET_INFO[network];
192
- if (!assetInfo) {
193
- throw new Error(`No USDC address configured for network: ${network}`);
194
- }
195
-
196
- const tokenAmount = convertToTokenAmount(
197
- String(amount),
198
- assetInfo.decimals,
199
- );
200
-
201
- return {
202
- asset: assetInfo.address,
203
- amount: tokenAmount,
204
- extra: {
205
- name: assetInfo.name,
206
- version: assetInfo.version,
207
- },
208
- };
209
- }
210
-
211
- /**
212
- * Enhance payment requirements with facilitator's extra fields.
213
- *
214
- * Merges supportedKind.extra (from facilitator's /supported endpoint) into
215
- * the requirements, so escrow addresses flow from facilitator → merchant
216
- * requirements automatically.
217
- */
218
- async enhancePaymentRequirements(
219
- requirements: PaymentRequirements,
220
- supportedKind: {
221
- x402Version: number;
222
- scheme: string;
223
- network: Network;
224
- extra?: Record<string, unknown>;
225
- },
226
- _facilitatorExtensions: string[],
227
- ): Promise<PaymentRequirements> {
228
- return {
229
- ...requirements,
230
- extra: {
231
- ...supportedKind.extra,
232
- ...requirements.extra,
233
- },
234
- };
235
- }
236
- }
237
-
238
- /**
239
- * Register escrow server scheme with x402ResourceServer
240
- *
241
- * @example
242
- * ```typescript
243
- * const server = new x402ResourceServer(facilitatorConfig);
244
- * registerEscrowServerScheme(server, { networks: "eip155:84532" });
245
- * ```
246
- */
247
- export function registerEscrowServerScheme(
248
- server: x402ResourceServer,
249
- config: { networks: Network | Network[] },
250
- ): x402ResourceServer {
251
- const scheme = new EscrowServerScheme();
252
- const networks = Array.isArray(config.networks)
253
- ? config.networks
254
- : [config.networks];
255
- for (const network of networks) {
256
- server.register(network, scheme);
257
- }
258
- return server;
259
- }
260
-
261
- export type { EscrowExtra, EscrowPayload } from "../../shared/types.js";
1
+ export { EscrowServerScheme } from './scheme'
2
+ export { registerEscrowEvmScheme } from './register'
3
+ export type { EvmResourceServerConfig } from './register'
@@ -0,0 +1,34 @@
1
+ import type { Network } from '@x402/core/types'
2
+ import { x402ResourceServer } from '@x402/core/server'
3
+ import { EscrowServerScheme } from './scheme'
4
+
5
+ export interface EvmResourceServerConfig {
6
+ networks?: Network | Network[]
7
+ }
8
+
9
+ /**
10
+ * Register escrow server scheme with x402ResourceServer
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const server = new x402ResourceServer(facilitatorConfig);
15
+ * registerEscrowEvmScheme(server);
16
+ * // or with specific networks:
17
+ * registerEscrowEvmScheme(server, { networks: "eip155:84532" });
18
+ * ```
19
+ */
20
+ export function registerEscrowEvmScheme(
21
+ server: x402ResourceServer,
22
+ config: EvmResourceServerConfig = {},
23
+ ): x402ResourceServer {
24
+ const scheme = new EscrowServerScheme()
25
+ const networks = config.networks
26
+ ? Array.isArray(config.networks)
27
+ ? config.networks
28
+ : [config.networks]
29
+ : ['eip155:*' as Network]
30
+ for (const network of networks) {
31
+ server.register(network, scheme)
32
+ }
33
+ return server
34
+ }