@x402r/extensions 0.0.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/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@x402r/extensions",
3
+ "version": "0.0.0",
4
+ "description": "x402 extensions - parent package for x402 extensions",
5
+ "type": "module",
6
+ "main": "./index.js",
7
+ "types": "./index.d.ts",
8
+ "exports": {
9
+ "./refund": {
10
+ "types": "./refund.d.ts",
11
+ "import": "./refund.mjs",
12
+ "require": "./refund.js"
13
+ },
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": [
17
+ "refund.mjs",
18
+ "refund.js",
19
+ "refund.d.ts"
20
+ ],
21
+ "license": "Apache-2.0",
22
+ "author": "Coinbase Inc.",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/BackTrackCo/x402r-extensions.git"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "dependencies": {
31
+ "@x402r/refund": "^0.0.0"
32
+ },
33
+ "peerDependencies": {
34
+ "@x402/core": "^2.0.0",
35
+ "@x402/evm": "^2.0.0"
36
+ }
37
+ }
package/refund.d.ts ADDED
@@ -0,0 +1,253 @@
1
+ import { PaymentOption, RoutesConfig } from '@x402/core/http';
2
+ import { PaymentPayload, PaymentRequirements, SettleResponse } from '@x402/core/types';
3
+ import { FacilitatorEvmSigner } from '@x402/evm';
4
+
5
+ /**
6
+ * Type definitions for the Refund Helper Extension
7
+ */
8
+
9
+ /**
10
+ * Extension identifier constant for the refund extension
11
+ */
12
+ declare const REFUND_EXTENSION_KEY = "refund";
13
+ /**
14
+ * Constant for the refund marker key (internal marker)
15
+ * Used to identify refundable payment options
16
+ * The merchantPayout is read directly from the option's payTo field when processing
17
+ */
18
+ declare const REFUND_MARKER_KEY = "_x402_refund";
19
+ /**
20
+ * Refund extension info structure
21
+ *
22
+ * merchantPayouts: Map of proxy address -> merchantPayout
23
+ * This allows multiple refundable options with different merchantPayouts
24
+ */
25
+ interface RefundExtensionInfo {
26
+ factoryAddress: string;
27
+ merchantPayouts: Record<string, string>;
28
+ }
29
+ /**
30
+ * Refund extension structure (matches extension pattern with info and schema)
31
+ */
32
+ interface RefundExtension {
33
+ info: RefundExtensionInfo;
34
+ schema: {
35
+ $schema: "https://json-schema.org/draft/2020-12/schema";
36
+ type: "object";
37
+ properties: {
38
+ factoryAddress: {
39
+ type: "string";
40
+ pattern: "^0x[a-fA-F0-9]{40}$";
41
+ description: "The X402DepositRelayFactory contract address";
42
+ };
43
+ merchantPayouts: {
44
+ type: "object";
45
+ additionalProperties: {
46
+ type: "string";
47
+ pattern: "^0x[a-fA-F0-9]{40}$";
48
+ };
49
+ description: "Map of proxy address to merchant payout address";
50
+ };
51
+ };
52
+ required: ["factoryAddress", "merchantPayouts"];
53
+ additionalProperties: false;
54
+ };
55
+ }
56
+ /**
57
+ * Type guard to check if a payment option is refundable
58
+ * A refundable option has a marker stored in extra
59
+ *
60
+ * @param option - The payment option to check
61
+ * @returns True if the option is refundable
62
+ */
63
+ declare function isRefundableOption(option: PaymentOption): boolean;
64
+
65
+ /**
66
+ * Server-side helpers for the Refund Helper Extension
67
+ *
68
+ * These helpers allow merchants to mark payment options as refundable
69
+ * and process route configurations to route payments to X402DepositRelayProxy contracts.
70
+ */
71
+
72
+ /**
73
+ * Declares a refund extension with factory address and merchantPayouts map
74
+ *
75
+ * @param factoryAddress - The X402DepositRelayFactory contract address
76
+ * @param merchantPayouts - Map of proxy address to merchant payout address
77
+ * @returns Refund extension object with info and schema
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const extension = declareRefundExtension("0xFactory123...", {
82
+ * "0xProxy1...": "0xMerchant1...",
83
+ * "0xProxy2...": "0xMerchant2...",
84
+ * });
85
+ * ```
86
+ */
87
+ declare function declareRefundExtension(factoryAddress: string, merchantPayouts: Record<string, string>): Record<string, RefundExtension>;
88
+ /**
89
+ * Marks a payment option as refundable.
90
+ *
91
+ * This function marks the option as refundable so it can be processed by `withRefund()`.
92
+ * The merchantPayout is read directly from the option's `payTo` field when processing.
93
+ *
94
+ * @param option - The payment option to mark as refundable
95
+ * @returns A new PaymentOption marked as refundable (does not mutate original)
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * const refundableOption = refundable({
100
+ * scheme: "exact",
101
+ * payTo: "0xmerchant123...",
102
+ * price: "$0.01",
103
+ * network: "eip155:84532",
104
+ * });
105
+ * // refundableOption.extra._x402_refund = true
106
+ * ```
107
+ */
108
+ declare function refundable(option: PaymentOption): PaymentOption;
109
+ /**
110
+ * Processes route configuration to handle refundable payment options.
111
+ *
112
+ * This function finds all payment options marked with `refundable()` and:
113
+ * 1. Computes the proxy address using CREATE3 (no bytecode needed!)
114
+ * 2. Sets `payTo` to the proxy address
115
+ * 3. Adds the refund extension with factory address
116
+ *
117
+ * @param routes - Route configuration (single RouteConfig or Record<string, RouteConfig>)
118
+ * @param factoryAddress - The X402DepositRelayFactory contract address (required)
119
+ * @param createxAddress - The CreateX contract address (optional, will use standard address for network if not provided)
120
+ * @returns A new RoutesConfig with refundable options routed to proxy (deep cloned, does not mutate original)
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * const routes = {
125
+ * "/api": {
126
+ * accepts: refundable({
127
+ * scheme: "exact",
128
+ * payTo: "0xmerchant123...",
129
+ * price: "$0.01",
130
+ * network: "eip155:84532",
131
+ * }),
132
+ * },
133
+ * };
134
+ *
135
+ * // Version is optional - defaults to config file value
136
+ * // CreateX address is optional - uses standard address for the network
137
+ * const processedRoutes = withRefund(routes, "0xFactory123...");
138
+ * // processedRoutes["/api"].accepts.payTo = computed proxy address
139
+ * // processedRoutes["/api"].extensions.refund = { info: { factoryAddress: "0xFactory123..." }, schema: {...} }
140
+ * ```
141
+ */
142
+ declare function withRefund(routes: RoutesConfig, factoryAddress: string, createxAddress?: string): RoutesConfig;
143
+
144
+ /**
145
+ * Helper to compute CREATE3 address for RelayProxy
146
+ *
147
+ * Uses the CREATE3 formula via CreateX (matching Solidity implementation):
148
+ *
149
+ * Where:
150
+ * - salt = keccak256(abi.encodePacked(factoryAddress, merchantPayout))
151
+ * - guardedSalt = keccak256(abi.encode(salt)) // CreateX guards the salt
152
+ * - createxDeployer = the CreateX contract address
153
+ *
154
+ * CREATE3 is much simpler than CREATE2 - no bytecode needed!
155
+ * The address depends only on the deployer (CreateX) and salt.
156
+ *
157
+ * IMPORTANT: The CreateX address must match the one used by the factory contract.
158
+ * The factory stores its CreateX address and can be queried via factory.getCreateX().
159
+ * This function computes addresses locally without any on-chain calls.
160
+ */
161
+ /**
162
+ * Computes the CREATE3 address for a merchant's relay proxy
163
+ *
164
+ * This matches the Solidity implementation in DepositRelayFactory.getRelayAddress():
165
+ * 1. salt = keccak256(abi.encodePacked(merchantPayout))
166
+ * 2. guardedSalt = keccak256(abi.encode(salt)) // CreateX guards the salt
167
+ * 3. return CREATEX.computeCreate3Address(guardedSalt)
168
+ *
169
+ * Uses the @whoislewys/predict-deterministic-address library which correctly
170
+ * implements the CREATE3 formula used by CreateX (based on Solady's CREATE3).
171
+ * This ensures the computed address matches the factory's on-chain computation
172
+ * without requiring any on-chain calls.
173
+ *
174
+ * @param createxAddress - The CreateX contract address
175
+ * @param factoryAddress - The DepositRelayFactory contract address
176
+ * @param merchantPayout - The merchant's payout address
177
+ * @returns The deterministic proxy address
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * // No bytecode needed! Computes locally without on-chain calls.
182
+ * const relayAddress = computeRelayAddress(
183
+ * "0xCreateX123...",
184
+ * "0xMerchant123...",
185
+ * 0n // version
186
+ * );
187
+ * ```
188
+ */
189
+ declare function computeRelayAddress(createxAddress: string, factoryAddress: string, merchantPayout: string): string;
190
+
191
+ /**
192
+ * Facilitator-side helpers for the Refund Helper Extension
193
+ *
194
+ * These helpers allow facilitator operators to validate refund info
195
+ * and handle refund settlements via X402DepositRelayProxy contracts.
196
+ */
197
+
198
+ /**
199
+ * Extracts refund extension info from payment payload or requirements
200
+ *
201
+ * @param paymentPayload - The payment payload (may contain extensions)
202
+ * @param _ - The payment requirements (currently unused, kept for API compatibility)
203
+ * @returns Refund extension info if valid, null otherwise
204
+ */
205
+ declare function extractRefundInfo(paymentPayload: PaymentPayload, _: PaymentRequirements): {
206
+ factoryAddress: string;
207
+ merchantPayouts: Record<string, string>;
208
+ } | null;
209
+ /**
210
+ * Helper for facilitator operators to handle refund settlements via X402DepositRelayProxy.
211
+ *
212
+ * This function:
213
+ * 1. Extracts refund extension info (factory address)
214
+ * 2. Validates factory exists
215
+ * 3. Reads merchantPayout and escrow directly from proxy storage
216
+ * 4. Checks if merchant is registered
217
+ * 5. Deploys relay on-demand if needed (via factory)
218
+ * 6. Calls proxy.executeDeposit() to deposit funds into escrow
219
+ *
220
+ * Returns null if refund is not applicable (delegates to normal flow).
221
+ * Throws error on execution failure or if merchant not registered (facilitator should handle in hook).
222
+ *
223
+ * @param paymentPayload - The payment payload containing authorization and signature
224
+ * @param paymentRequirements - The payment requirements containing refund extension
225
+ * @param signer - The EVM signer for contract interactions
226
+ * @returns SettleResponse on success, null if not applicable
227
+ * @throws Error on execution failure or if merchant not registered
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * facilitator.onBeforeSettle(async (context) => {
232
+ * try {
233
+ * const result = await settleWithRefundHelper(
234
+ * context.paymentPayload,
235
+ * context.paymentRequirements,
236
+ * signer,
237
+ * );
238
+ *
239
+ * if (result) {
240
+ * return { abort: true, reason: 'handled_by_refund_helper' };
241
+ * }
242
+ * } catch (error) {
243
+ * // Log error but don't abort - let normal settlement proceed
244
+ * console.error('Refund helper settlement failed:', error);
245
+ * }
246
+ *
247
+ * return null; // Proceed with normal settlement
248
+ * });
249
+ * ```
250
+ */
251
+ declare function settleWithRefundHelper(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements, signer: FacilitatorEvmSigner): Promise<SettleResponse | null>;
252
+
253
+ export { REFUND_EXTENSION_KEY, REFUND_MARKER_KEY, type RefundExtension, type RefundExtensionInfo, computeRelayAddress, declareRefundExtension, extractRefundInfo, isRefundableOption, refundable, settleWithRefundHelper, withRefund };
package/refund.js ADDED
@@ -0,0 +1,2 @@
1
+ module.exports = require('@x402r/refund');
2
+
package/refund.mjs ADDED
@@ -0,0 +1,2 @@
1
+ export * from '@x402r/refund';
2
+