@pafi-dev/trading 0.2.0 → 0.3.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 +132 -378
- package/dist/index.cjs +63 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -51
- package/dist/index.d.ts +75 -51
- package/dist/index.js +65 -36
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -22,8 +22,26 @@ type ApiQuoteError = "QUOTE_UNAVAILABLE" | "AMOUNT_TOO_SMALL_FOR_GAS";
|
|
|
22
22
|
interface ApiQuoteResponse {
|
|
23
23
|
/** Echoes `request.amount` for FE bookkeeping. */
|
|
24
24
|
inputAmount: bigint;
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Gross output from the V4 quoter — before operator fee deduction.
|
|
27
|
+
* Use for "you swap X for ~Y" UI; do not promise this number to user.
|
|
28
|
+
* 0n when `quoteError` set.
|
|
29
|
+
*/
|
|
26
30
|
estimatedOutputAmount: bigint;
|
|
31
|
+
/**
|
|
32
|
+
* Net output after the operator fee transfer is subtracted from the
|
|
33
|
+
* gross. This is what the user actually receives in their wallet.
|
|
34
|
+
* `outputNet = estimatedOutputAmount - feeAmountOutput`.
|
|
35
|
+
*
|
|
36
|
+
* v0.3 — added when fee model switched to output-side. Display this
|
|
37
|
+
* to the user; the on-chain post-swap fee transfer enforces it.
|
|
38
|
+
*/
|
|
39
|
+
outputNet: bigint;
|
|
40
|
+
/**
|
|
41
|
+
* Operator gas fee deducted from the swap output, in OUTPUT token
|
|
42
|
+
* raw units. 0n on the fallback path or when handler couldn't quote.
|
|
43
|
+
*/
|
|
44
|
+
feeAmountOutput: bigint;
|
|
27
45
|
/** V4 Quoter's gas estimate for the route. */
|
|
28
46
|
gasEstimate: bigint;
|
|
29
47
|
quoteError?: ApiQuoteError;
|
|
@@ -46,15 +64,19 @@ interface ApiSwapRequest {
|
|
|
46
64
|
/** Pools to consider. Caller pre-fetches per-PT pools and merges. */
|
|
47
65
|
pools?: PoolKey[];
|
|
48
66
|
/**
|
|
49
|
-
* Operator fee in
|
|
50
|
-
* reimbursement for sponsoring ERC-4337 gas.
|
|
67
|
+
* Operator fee in OUTPUT token units, paid to PAFI fee recipient as
|
|
68
|
+
* reimbursement for sponsoring ERC-4337 gas. Applied AFTER the swap.
|
|
51
69
|
*
|
|
52
70
|
* - `undefined` (default): handler auto-quotes via
|
|
53
|
-
* `
|
|
71
|
+
* `quoteOperatorFeeUsdt` when output is USDT, `quoteOperatorFeePt`
|
|
72
|
+
* when output is a PT.
|
|
54
73
|
* - `0n`: strip the fee transfer (unsponsored fallback path).
|
|
55
74
|
* - explicit `bigint`: override for issuer markup/subsidy scenarios.
|
|
75
|
+
*
|
|
76
|
+
* v0.3 — renamed from `gasFeeAmount` (input-side). See
|
|
77
|
+
* SDK_ARCHITECTURE.md "Fee positioning rule".
|
|
56
78
|
*/
|
|
57
|
-
|
|
79
|
+
gasFeeAmountOutput?: bigint;
|
|
58
80
|
}
|
|
59
81
|
interface ApiSwapResponse {
|
|
60
82
|
/** Unsigned UserOp — attach paymaster + user signature, submit to Bundler. */
|
|
@@ -74,7 +96,8 @@ interface ApiSwapResponse {
|
|
|
74
96
|
deadline: bigint;
|
|
75
97
|
/**
|
|
76
98
|
* Operator fee amount embedded — echoes auto-quote result or override.
|
|
77
|
-
* Denominated in the
|
|
99
|
+
* Denominated in the OUTPUT token (v0.3+). `0n` when caller forced
|
|
100
|
+
* no-fee mode.
|
|
78
101
|
*/
|
|
79
102
|
feeAmountUsed: bigint;
|
|
80
103
|
feeRecipient: Address;
|
|
@@ -124,22 +147,18 @@ interface ApiPerpDepositRequest {
|
|
|
124
147
|
*/
|
|
125
148
|
maxRelayFee?: bigint;
|
|
126
149
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
* omitted, the handler skips the fee transfer entirely; useful for
|
|
130
|
-
* the unsponsored fallback variant.
|
|
131
|
-
*/
|
|
132
|
-
pointTokenAddress?: Address;
|
|
133
|
-
/**
|
|
134
|
-
* PT operator fee. Same semantics as `ApiSwapRequest.gasFeePt`:
|
|
135
|
-
* - `undefined` (default): auto-quote via `quoteOperatorFeePt`
|
|
136
|
-
* - `0n`: strip fee transfer (force unsponsored mode)
|
|
137
|
-
* - explicit `bigint`: override
|
|
150
|
+
* USDC operator fee — paid as input-token transfer prepended to the
|
|
151
|
+
* batch (token-availability rule: user holds USDC before deposit).
|
|
138
152
|
*
|
|
139
|
-
* `
|
|
140
|
-
*
|
|
153
|
+
* - `undefined` (default): auto-quote via `quoteOperatorFeeUsdt`
|
|
154
|
+
* (USDC = stablecoin 6-dec, same shape).
|
|
155
|
+
* - `0n`: strip fee transfer (force unsponsored mode).
|
|
156
|
+
* - explicit `bigint`: override.
|
|
157
|
+
*
|
|
158
|
+
* v0.3 — replaced PT-side fee (`gasFeePt` + `pointTokenAddress`).
|
|
159
|
+
* User now needs only USDC to complete the deposit.
|
|
141
160
|
*/
|
|
142
|
-
|
|
161
|
+
gasFeeUsdc?: bigint;
|
|
143
162
|
}
|
|
144
163
|
interface ApiPerpDepositResponse {
|
|
145
164
|
/** Unsigned UserOp — attach paymaster data + user signature, then submit to Bundler. */
|
|
@@ -223,13 +242,16 @@ declare class TradingHandlers {
|
|
|
223
242
|
*/
|
|
224
243
|
handleQuote(request: ApiQuoteRequest): Promise<ApiQuoteResponse>;
|
|
225
244
|
/**
|
|
226
|
-
* Build a
|
|
245
|
+
* Build a swap UserOp (direction-agnostic).
|
|
227
246
|
*
|
|
228
247
|
* Quotes the best route, applies slippage, then encodes a 4-step
|
|
229
|
-
* batch:
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
248
|
+
* batch: input.approve → Permit2.approve → UniversalRouter.execute →
|
|
249
|
+
* output.transfer (fee in OUTPUT token, omitted when fee = 0).
|
|
250
|
+
*
|
|
251
|
+
* v0.3 — Fee model is OUTPUT-side (token-availability rule). User
|
|
252
|
+
* holds exactly `amountIn` of input; receives `outputGross - fee`
|
|
253
|
+
* net. Quote response surfaces both `estimatedOutputAmount` (gross)
|
|
254
|
+
* and `outputNet` so the FE can display reality.
|
|
233
255
|
*/
|
|
234
256
|
handleSwap(request: ApiSwapRequest): Promise<ApiSwapResponse>;
|
|
235
257
|
/**
|
|
@@ -329,7 +351,7 @@ interface SwapSimulationResult {
|
|
|
329
351
|
declare function simulateSwap(client: PublicClient, routerAddress: Address, commands: Hex, inputs: Hex[], deadline: bigint, from: Address): Promise<SwapSimulationResult>;
|
|
330
352
|
|
|
331
353
|
/**
|
|
332
|
-
*
|
|
354
|
+
* v0.3 — Generalized swap UserOp builder. Direction-agnostic: works
|
|
333
355
|
* for **any** ERC-20 → ERC-20 pair routable through PAFI's V4 pools:
|
|
334
356
|
*
|
|
335
357
|
* - PT → USDT (cashout)
|
|
@@ -338,22 +360,27 @@ declare function simulateSwap(client: PublicClient, routerAddress: Address, comm
|
|
|
338
360
|
*
|
|
339
361
|
* UserOp shape (atomic batch via EIP-7702 BatchExecutor):
|
|
340
362
|
*
|
|
341
|
-
* 1. `inputToken.approve(Permit2, amountIn
|
|
342
|
-
* approve covers both swap input + operator gas reimbursement.
|
|
363
|
+
* 1. `inputToken.approve(Permit2, amountIn)` — exactly the swap amount.
|
|
343
364
|
* 2. `Permit2.approve(inputToken, router, amountIn, deadline)` — Permit2
|
|
344
365
|
* authorization to UniversalRouter.
|
|
345
366
|
* 3. `UniversalRouter.execute(commands, inputs, deadline)` — V4 swap
|
|
346
367
|
* `inputToken → outputToken`; user receives ≥ `minAmountOut`.
|
|
347
|
-
* 4. `
|
|
348
|
-
* gas reimbursement, paid in
|
|
368
|
+
* 4. `outputToken.transfer(feeRecipient, gasFeeAmountOutput)` —
|
|
369
|
+
* operator gas reimbursement, paid in OUTPUT token (omitted when 0).
|
|
349
370
|
*
|
|
350
|
-
* ## Fee model —
|
|
371
|
+
* ## Fee model — output-token strategy (token-availability rule)
|
|
351
372
|
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
* single token in sufficient quantity.
|
|
373
|
+
* Fee is charged in the **output token** AFTER the swap, because the
|
|
374
|
+
* user holds output token at that point in the batch. Three benefits:
|
|
355
375
|
*
|
|
356
|
-
* User
|
|
376
|
+
* - User holds exactly `amountIn` of input token (FE quote = chain
|
|
377
|
+
* reality). No "you need 1010 to swap 1000" UX surprise.
|
|
378
|
+
* - Quote API returns `outputNet = outputGross - feeOutput` directly,
|
|
379
|
+
* matching what user actually receives.
|
|
380
|
+
* - PT → USDT: PAFI receives USDT (universally liquid, clean accounting).
|
|
381
|
+
*
|
|
382
|
+
* Caller MUST ensure `minAmountOut >= gasFeeAmountOutput` (fee transfer
|
|
383
|
+
* reverts otherwise → whole batch reverts).
|
|
357
384
|
*
|
|
358
385
|
* ## PAFI Hook fee
|
|
359
386
|
*
|
|
@@ -365,11 +392,6 @@ declare function simulateSwap(client: PublicClient, routerAddress: Address, comm
|
|
|
365
392
|
* - PT → USDT: pool charges 10% (output reduced)
|
|
366
393
|
* - USDT → PT: no hook fee
|
|
367
394
|
* - PT0 → PT1: 10% on PT0 → USDT leg, 0% on USDT → PT1 leg
|
|
368
|
-
*
|
|
369
|
-
* ## Order of operations
|
|
370
|
-
*
|
|
371
|
-
* Fee transfer is LAST so a reverting swap also refunds the fee
|
|
372
|
-
* (atomic batch revert semantics).
|
|
373
395
|
*/
|
|
374
396
|
interface BuildSwapUserOpParams {
|
|
375
397
|
/** User's EOA (with EIP-7702 delegation to BatchExecutor). */
|
|
@@ -382,12 +404,12 @@ interface BuildSwapUserOpParams {
|
|
|
382
404
|
outputTokenAddress: Address;
|
|
383
405
|
/** UniversalRouter contract address (chain-specific). */
|
|
384
406
|
universalRouterAddress: Address;
|
|
385
|
-
/** Input token units to swap. User
|
|
407
|
+
/** Input token units to swap. User must hold exactly this much input token. */
|
|
386
408
|
amountIn: bigint;
|
|
387
409
|
/**
|
|
388
|
-
* Minimum output to accept. Caller applies
|
|
389
|
-
*
|
|
390
|
-
*
|
|
410
|
+
* Minimum output (gross) to accept from the swap. Caller applies
|
|
411
|
+
* slippage against a fresh quote. MUST be ≥ `gasFeeAmountOutput` or
|
|
412
|
+
* the post-swap fee transfer reverts.
|
|
391
413
|
*/
|
|
392
414
|
minAmountOut: bigint;
|
|
393
415
|
/**
|
|
@@ -398,12 +420,14 @@ interface BuildSwapUserOpParams {
|
|
|
398
420
|
/** Unix seconds. After this, the router rejects the swap. */
|
|
399
421
|
deadline: bigint;
|
|
400
422
|
/**
|
|
401
|
-
* Operator gas-reimbursement fee — paid in
|
|
402
|
-
* the batch when 0n. Caller
|
|
403
|
-
*
|
|
404
|
-
*
|
|
423
|
+
* Operator gas-reimbursement fee — paid in OUTPUT token. Omitted
|
|
424
|
+
* from the batch when 0n. Caller quotes this via `quoteOperatorFee*`
|
|
425
|
+
* helpers (USDT/PT depending on output token).
|
|
426
|
+
*
|
|
427
|
+
* v0.3 — switched from input-side fee (v0.2 `gasFeeAmount`) to
|
|
428
|
+
* output-side fee. See "Fee model" comment above.
|
|
405
429
|
*/
|
|
406
|
-
|
|
430
|
+
gasFeeAmountOutput: bigint;
|
|
407
431
|
/**
|
|
408
432
|
* Where the gas fee lands — typically the canonical PAFI fee
|
|
409
433
|
* recipient from `getContractAddresses(chainId).pafiFeeRecipient`.
|
|
@@ -419,8 +443,8 @@ interface BuildSwapUserOpParams {
|
|
|
419
443
|
/**
|
|
420
444
|
* Build an unsigned UserOp for the generalized swap flow.
|
|
421
445
|
*
|
|
422
|
-
* @throws when `amountIn` is non-positive, `
|
|
423
|
-
*
|
|
446
|
+
* @throws when `amountIn` is non-positive, `gasFeeAmountOutput` is
|
|
447
|
+
* negative, `swapPath` is empty, or `minAmountOut < gasFeeAmountOutput`.
|
|
424
448
|
*/
|
|
425
449
|
declare function buildSwapUserOp(params: BuildSwapUserOpParams): PartialUserOperation;
|
|
426
450
|
|
package/dist/index.d.ts
CHANGED
|
@@ -22,8 +22,26 @@ type ApiQuoteError = "QUOTE_UNAVAILABLE" | "AMOUNT_TOO_SMALL_FOR_GAS";
|
|
|
22
22
|
interface ApiQuoteResponse {
|
|
23
23
|
/** Echoes `request.amount` for FE bookkeeping. */
|
|
24
24
|
inputAmount: bigint;
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Gross output from the V4 quoter — before operator fee deduction.
|
|
27
|
+
* Use for "you swap X for ~Y" UI; do not promise this number to user.
|
|
28
|
+
* 0n when `quoteError` set.
|
|
29
|
+
*/
|
|
26
30
|
estimatedOutputAmount: bigint;
|
|
31
|
+
/**
|
|
32
|
+
* Net output after the operator fee transfer is subtracted from the
|
|
33
|
+
* gross. This is what the user actually receives in their wallet.
|
|
34
|
+
* `outputNet = estimatedOutputAmount - feeAmountOutput`.
|
|
35
|
+
*
|
|
36
|
+
* v0.3 — added when fee model switched to output-side. Display this
|
|
37
|
+
* to the user; the on-chain post-swap fee transfer enforces it.
|
|
38
|
+
*/
|
|
39
|
+
outputNet: bigint;
|
|
40
|
+
/**
|
|
41
|
+
* Operator gas fee deducted from the swap output, in OUTPUT token
|
|
42
|
+
* raw units. 0n on the fallback path or when handler couldn't quote.
|
|
43
|
+
*/
|
|
44
|
+
feeAmountOutput: bigint;
|
|
27
45
|
/** V4 Quoter's gas estimate for the route. */
|
|
28
46
|
gasEstimate: bigint;
|
|
29
47
|
quoteError?: ApiQuoteError;
|
|
@@ -46,15 +64,19 @@ interface ApiSwapRequest {
|
|
|
46
64
|
/** Pools to consider. Caller pre-fetches per-PT pools and merges. */
|
|
47
65
|
pools?: PoolKey[];
|
|
48
66
|
/**
|
|
49
|
-
* Operator fee in
|
|
50
|
-
* reimbursement for sponsoring ERC-4337 gas.
|
|
67
|
+
* Operator fee in OUTPUT token units, paid to PAFI fee recipient as
|
|
68
|
+
* reimbursement for sponsoring ERC-4337 gas. Applied AFTER the swap.
|
|
51
69
|
*
|
|
52
70
|
* - `undefined` (default): handler auto-quotes via
|
|
53
|
-
* `
|
|
71
|
+
* `quoteOperatorFeeUsdt` when output is USDT, `quoteOperatorFeePt`
|
|
72
|
+
* when output is a PT.
|
|
54
73
|
* - `0n`: strip the fee transfer (unsponsored fallback path).
|
|
55
74
|
* - explicit `bigint`: override for issuer markup/subsidy scenarios.
|
|
75
|
+
*
|
|
76
|
+
* v0.3 — renamed from `gasFeeAmount` (input-side). See
|
|
77
|
+
* SDK_ARCHITECTURE.md "Fee positioning rule".
|
|
56
78
|
*/
|
|
57
|
-
|
|
79
|
+
gasFeeAmountOutput?: bigint;
|
|
58
80
|
}
|
|
59
81
|
interface ApiSwapResponse {
|
|
60
82
|
/** Unsigned UserOp — attach paymaster + user signature, submit to Bundler. */
|
|
@@ -74,7 +96,8 @@ interface ApiSwapResponse {
|
|
|
74
96
|
deadline: bigint;
|
|
75
97
|
/**
|
|
76
98
|
* Operator fee amount embedded — echoes auto-quote result or override.
|
|
77
|
-
* Denominated in the
|
|
99
|
+
* Denominated in the OUTPUT token (v0.3+). `0n` when caller forced
|
|
100
|
+
* no-fee mode.
|
|
78
101
|
*/
|
|
79
102
|
feeAmountUsed: bigint;
|
|
80
103
|
feeRecipient: Address;
|
|
@@ -124,22 +147,18 @@ interface ApiPerpDepositRequest {
|
|
|
124
147
|
*/
|
|
125
148
|
maxRelayFee?: bigint;
|
|
126
149
|
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
* omitted, the handler skips the fee transfer entirely; useful for
|
|
130
|
-
* the unsponsored fallback variant.
|
|
131
|
-
*/
|
|
132
|
-
pointTokenAddress?: Address;
|
|
133
|
-
/**
|
|
134
|
-
* PT operator fee. Same semantics as `ApiSwapRequest.gasFeePt`:
|
|
135
|
-
* - `undefined` (default): auto-quote via `quoteOperatorFeePt`
|
|
136
|
-
* - `0n`: strip fee transfer (force unsponsored mode)
|
|
137
|
-
* - explicit `bigint`: override
|
|
150
|
+
* USDC operator fee — paid as input-token transfer prepended to the
|
|
151
|
+
* batch (token-availability rule: user holds USDC before deposit).
|
|
138
152
|
*
|
|
139
|
-
* `
|
|
140
|
-
*
|
|
153
|
+
* - `undefined` (default): auto-quote via `quoteOperatorFeeUsdt`
|
|
154
|
+
* (USDC = stablecoin 6-dec, same shape).
|
|
155
|
+
* - `0n`: strip fee transfer (force unsponsored mode).
|
|
156
|
+
* - explicit `bigint`: override.
|
|
157
|
+
*
|
|
158
|
+
* v0.3 — replaced PT-side fee (`gasFeePt` + `pointTokenAddress`).
|
|
159
|
+
* User now needs only USDC to complete the deposit.
|
|
141
160
|
*/
|
|
142
|
-
|
|
161
|
+
gasFeeUsdc?: bigint;
|
|
143
162
|
}
|
|
144
163
|
interface ApiPerpDepositResponse {
|
|
145
164
|
/** Unsigned UserOp — attach paymaster data + user signature, then submit to Bundler. */
|
|
@@ -223,13 +242,16 @@ declare class TradingHandlers {
|
|
|
223
242
|
*/
|
|
224
243
|
handleQuote(request: ApiQuoteRequest): Promise<ApiQuoteResponse>;
|
|
225
244
|
/**
|
|
226
|
-
* Build a
|
|
245
|
+
* Build a swap UserOp (direction-agnostic).
|
|
227
246
|
*
|
|
228
247
|
* Quotes the best route, applies slippage, then encodes a 4-step
|
|
229
|
-
* batch:
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
248
|
+
* batch: input.approve → Permit2.approve → UniversalRouter.execute →
|
|
249
|
+
* output.transfer (fee in OUTPUT token, omitted when fee = 0).
|
|
250
|
+
*
|
|
251
|
+
* v0.3 — Fee model is OUTPUT-side (token-availability rule). User
|
|
252
|
+
* holds exactly `amountIn` of input; receives `outputGross - fee`
|
|
253
|
+
* net. Quote response surfaces both `estimatedOutputAmount` (gross)
|
|
254
|
+
* and `outputNet` so the FE can display reality.
|
|
233
255
|
*/
|
|
234
256
|
handleSwap(request: ApiSwapRequest): Promise<ApiSwapResponse>;
|
|
235
257
|
/**
|
|
@@ -329,7 +351,7 @@ interface SwapSimulationResult {
|
|
|
329
351
|
declare function simulateSwap(client: PublicClient, routerAddress: Address, commands: Hex, inputs: Hex[], deadline: bigint, from: Address): Promise<SwapSimulationResult>;
|
|
330
352
|
|
|
331
353
|
/**
|
|
332
|
-
*
|
|
354
|
+
* v0.3 — Generalized swap UserOp builder. Direction-agnostic: works
|
|
333
355
|
* for **any** ERC-20 → ERC-20 pair routable through PAFI's V4 pools:
|
|
334
356
|
*
|
|
335
357
|
* - PT → USDT (cashout)
|
|
@@ -338,22 +360,27 @@ declare function simulateSwap(client: PublicClient, routerAddress: Address, comm
|
|
|
338
360
|
*
|
|
339
361
|
* UserOp shape (atomic batch via EIP-7702 BatchExecutor):
|
|
340
362
|
*
|
|
341
|
-
* 1. `inputToken.approve(Permit2, amountIn
|
|
342
|
-
* approve covers both swap input + operator gas reimbursement.
|
|
363
|
+
* 1. `inputToken.approve(Permit2, amountIn)` — exactly the swap amount.
|
|
343
364
|
* 2. `Permit2.approve(inputToken, router, amountIn, deadline)` — Permit2
|
|
344
365
|
* authorization to UniversalRouter.
|
|
345
366
|
* 3. `UniversalRouter.execute(commands, inputs, deadline)` — V4 swap
|
|
346
367
|
* `inputToken → outputToken`; user receives ≥ `minAmountOut`.
|
|
347
|
-
* 4. `
|
|
348
|
-
* gas reimbursement, paid in
|
|
368
|
+
* 4. `outputToken.transfer(feeRecipient, gasFeeAmountOutput)` —
|
|
369
|
+
* operator gas reimbursement, paid in OUTPUT token (omitted when 0).
|
|
349
370
|
*
|
|
350
|
-
* ## Fee model —
|
|
371
|
+
* ## Fee model — output-token strategy (token-availability rule)
|
|
351
372
|
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
* single token in sufficient quantity.
|
|
373
|
+
* Fee is charged in the **output token** AFTER the swap, because the
|
|
374
|
+
* user holds output token at that point in the batch. Three benefits:
|
|
355
375
|
*
|
|
356
|
-
* User
|
|
376
|
+
* - User holds exactly `amountIn` of input token (FE quote = chain
|
|
377
|
+
* reality). No "you need 1010 to swap 1000" UX surprise.
|
|
378
|
+
* - Quote API returns `outputNet = outputGross - feeOutput` directly,
|
|
379
|
+
* matching what user actually receives.
|
|
380
|
+
* - PT → USDT: PAFI receives USDT (universally liquid, clean accounting).
|
|
381
|
+
*
|
|
382
|
+
* Caller MUST ensure `minAmountOut >= gasFeeAmountOutput` (fee transfer
|
|
383
|
+
* reverts otherwise → whole batch reverts).
|
|
357
384
|
*
|
|
358
385
|
* ## PAFI Hook fee
|
|
359
386
|
*
|
|
@@ -365,11 +392,6 @@ declare function simulateSwap(client: PublicClient, routerAddress: Address, comm
|
|
|
365
392
|
* - PT → USDT: pool charges 10% (output reduced)
|
|
366
393
|
* - USDT → PT: no hook fee
|
|
367
394
|
* - PT0 → PT1: 10% on PT0 → USDT leg, 0% on USDT → PT1 leg
|
|
368
|
-
*
|
|
369
|
-
* ## Order of operations
|
|
370
|
-
*
|
|
371
|
-
* Fee transfer is LAST so a reverting swap also refunds the fee
|
|
372
|
-
* (atomic batch revert semantics).
|
|
373
395
|
*/
|
|
374
396
|
interface BuildSwapUserOpParams {
|
|
375
397
|
/** User's EOA (with EIP-7702 delegation to BatchExecutor). */
|
|
@@ -382,12 +404,12 @@ interface BuildSwapUserOpParams {
|
|
|
382
404
|
outputTokenAddress: Address;
|
|
383
405
|
/** UniversalRouter contract address (chain-specific). */
|
|
384
406
|
universalRouterAddress: Address;
|
|
385
|
-
/** Input token units to swap. User
|
|
407
|
+
/** Input token units to swap. User must hold exactly this much input token. */
|
|
386
408
|
amountIn: bigint;
|
|
387
409
|
/**
|
|
388
|
-
* Minimum output to accept. Caller applies
|
|
389
|
-
*
|
|
390
|
-
*
|
|
410
|
+
* Minimum output (gross) to accept from the swap. Caller applies
|
|
411
|
+
* slippage against a fresh quote. MUST be ≥ `gasFeeAmountOutput` or
|
|
412
|
+
* the post-swap fee transfer reverts.
|
|
391
413
|
*/
|
|
392
414
|
minAmountOut: bigint;
|
|
393
415
|
/**
|
|
@@ -398,12 +420,14 @@ interface BuildSwapUserOpParams {
|
|
|
398
420
|
/** Unix seconds. After this, the router rejects the swap. */
|
|
399
421
|
deadline: bigint;
|
|
400
422
|
/**
|
|
401
|
-
* Operator gas-reimbursement fee — paid in
|
|
402
|
-
* the batch when 0n. Caller
|
|
403
|
-
*
|
|
404
|
-
*
|
|
423
|
+
* Operator gas-reimbursement fee — paid in OUTPUT token. Omitted
|
|
424
|
+
* from the batch when 0n. Caller quotes this via `quoteOperatorFee*`
|
|
425
|
+
* helpers (USDT/PT depending on output token).
|
|
426
|
+
*
|
|
427
|
+
* v0.3 — switched from input-side fee (v0.2 `gasFeeAmount`) to
|
|
428
|
+
* output-side fee. See "Fee model" comment above.
|
|
405
429
|
*/
|
|
406
|
-
|
|
430
|
+
gasFeeAmountOutput: bigint;
|
|
407
431
|
/**
|
|
408
432
|
* Where the gas fee lands — typically the canonical PAFI fee
|
|
409
433
|
* recipient from `getContractAddresses(chainId).pafiFeeRecipient`.
|
|
@@ -419,8 +443,8 @@ interface BuildSwapUserOpParams {
|
|
|
419
443
|
/**
|
|
420
444
|
* Build an unsigned UserOp for the generalized swap flow.
|
|
421
445
|
*
|
|
422
|
-
* @throws when `amountIn` is non-positive, `
|
|
423
|
-
*
|
|
446
|
+
* @throws when `amountIn` is non-positive, `gasFeeAmountOutput` is
|
|
447
|
+
* negative, `swapPath` is empty, or `minAmountOut < gasFeeAmountOutput`.
|
|
424
448
|
*/
|
|
425
449
|
declare function buildSwapUserOp(params: BuildSwapUserOpParams): PartialUserOperation;
|
|
426
450
|
|