@pafi-dev/trading 0.3.3 → 0.4.1
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 +95 -0
- package/dist/index.cjs +840 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +541 -19
- package/dist/index.d.ts +541 -19
- package/dist/index.js +854 -14
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Address, PublicClient, Hex } from 'viem';
|
|
2
|
-
import { PartialUserOperation, PoolKey, QuoteResult, PathKey, BestQuote } from '@pafi-dev/core';
|
|
1
|
+
import { Address, PublicClient, Hex, WalletClient, TransactionReceipt } from 'viem';
|
|
2
|
+
import { PartialUserOperation, PoolKey, QuoteResult, PathKey, BestQuote, ExactOutputBestQuote, ExactOutputQuoteResult, BROKER_HASHES } from '@pafi-dev/core';
|
|
3
3
|
export { PAFI_SUBGRAPH_URL, fetchPafiPools } from '@pafi-dev/core';
|
|
4
4
|
|
|
5
5
|
interface ApiQuoteRequest {
|
|
@@ -102,6 +102,95 @@ interface ApiSwapResponse {
|
|
|
102
102
|
feeAmountUsed: bigint;
|
|
103
103
|
feeRecipient: Address;
|
|
104
104
|
}
|
|
105
|
+
interface ApiQuoteExactOutRequest {
|
|
106
|
+
chainId: number;
|
|
107
|
+
/** Token user is spending. */
|
|
108
|
+
inputTokenAddress: Address;
|
|
109
|
+
/** Token user wants to receive. */
|
|
110
|
+
outputTokenAddress: Address;
|
|
111
|
+
/** Exact OUTPUT token amount the user wants (raw decimals). */
|
|
112
|
+
amount: bigint;
|
|
113
|
+
/** Pools to include in routing. Combined with COMMON_POOLS. */
|
|
114
|
+
pools?: PoolKey[];
|
|
115
|
+
}
|
|
116
|
+
interface ApiQuoteExactOutResponse {
|
|
117
|
+
/** Echoes `request.amount` — the exact output amount. */
|
|
118
|
+
outputAmount: bigint;
|
|
119
|
+
/**
|
|
120
|
+
* Gross input required from the V4 quoter — before operator fee. Use
|
|
121
|
+
* for "you'll pay ~X PT for exactly Y USDT" UI; do not promise this
|
|
122
|
+
* number without slippage bounding. 0n when `quoteError` set.
|
|
123
|
+
*/
|
|
124
|
+
estimatedInputAmount: bigint;
|
|
125
|
+
/**
|
|
126
|
+
* Total input the user must hold = `estimatedInputAmount + feeAmountInput`.
|
|
127
|
+
* Display this as the "you pay" number alongside the exact output amount.
|
|
128
|
+
*/
|
|
129
|
+
inputGross: bigint;
|
|
130
|
+
/**
|
|
131
|
+
* Operator gas fee charged on the INPUT token side, raw units. 0n on
|
|
132
|
+
* fallback path or when handler couldn't quote.
|
|
133
|
+
*/
|
|
134
|
+
feeAmountInput: bigint;
|
|
135
|
+
/** V4 Quoter's gas estimate for the route. */
|
|
136
|
+
gasEstimate: bigint;
|
|
137
|
+
quoteError?: ApiQuoteError;
|
|
138
|
+
}
|
|
139
|
+
interface ApiSwapExactOutRequest {
|
|
140
|
+
chainId: number;
|
|
141
|
+
userAddress: Address;
|
|
142
|
+
inputTokenAddress: Address;
|
|
143
|
+
outputTokenAddress: Address;
|
|
144
|
+
/** Exact OUTPUT token amount the user wants (raw decimals). */
|
|
145
|
+
amount: bigint;
|
|
146
|
+
/** ERC-4337 account nonce for the user's EOA (from EntryPoint). */
|
|
147
|
+
aaNonce: bigint;
|
|
148
|
+
/**
|
|
149
|
+
* Slippage tolerance in basis points (1 bps = 0.01%). Default: 50
|
|
150
|
+
* for single-hop, 100 for multi-hop. Slippage caps `maxAmountIn`
|
|
151
|
+
* upward (ceiling division) — the user agrees to spend up to this
|
|
152
|
+
* much extra to lock in the exact output.
|
|
153
|
+
*/
|
|
154
|
+
slippageBps?: number;
|
|
155
|
+
/** Pools to consider. */
|
|
156
|
+
pools?: PoolKey[];
|
|
157
|
+
/**
|
|
158
|
+
* Operator fee in INPUT token units, paid to PAFI fee recipient
|
|
159
|
+
* BEFORE the swap. Charged input-side because exact-output promises
|
|
160
|
+
* the user a precise output amount.
|
|
161
|
+
*
|
|
162
|
+
* - `undefined` (default): handler auto-quotes via the operator-fee
|
|
163
|
+
* helper appropriate to `inputTokenAddress` (USDT/USDC/PT).
|
|
164
|
+
* - `0n`: strip the fee transfer (unsponsored fallback path).
|
|
165
|
+
* - explicit `bigint`: override.
|
|
166
|
+
*/
|
|
167
|
+
gasFeeAmountInput?: bigint;
|
|
168
|
+
}
|
|
169
|
+
interface ApiSwapExactOutResponse {
|
|
170
|
+
/** Unsigned UserOp — attach paymaster + user signature, submit to Bundler. */
|
|
171
|
+
userOp: PartialUserOperation;
|
|
172
|
+
/**
|
|
173
|
+
* Fee-stripped fallback variant. Emitted only when `gasFeeAmountInput > 0`.
|
|
174
|
+
* Submit when the paymaster refuses sponsorship.
|
|
175
|
+
*/
|
|
176
|
+
userOpFallback?: PartialUserOperation;
|
|
177
|
+
/** Echoes `request.amount` — the exact output. */
|
|
178
|
+
outputAmount: bigint;
|
|
179
|
+
/** Raw input amount from the V4 quoter, before slippage. For display. */
|
|
180
|
+
estimatedInputAmount: bigint;
|
|
181
|
+
/** Maximum input accepted — encoded in the UserOp calldata. */
|
|
182
|
+
maxAmountIn: bigint;
|
|
183
|
+
/** Number of hops in the chosen route. */
|
|
184
|
+
hops: number;
|
|
185
|
+
/** Swap deadline (unix seconds). */
|
|
186
|
+
deadline: bigint;
|
|
187
|
+
/**
|
|
188
|
+
* Operator fee amount embedded — echoes auto-quote or override.
|
|
189
|
+
* Denominated in the INPUT token. `0n` when no-fee mode.
|
|
190
|
+
*/
|
|
191
|
+
feeAmountUsed: bigint;
|
|
192
|
+
feeRecipient: Address;
|
|
193
|
+
}
|
|
105
194
|
interface ApiPerpDepositRequest {
|
|
106
195
|
chainId: number;
|
|
107
196
|
userAddress: Address;
|
|
@@ -253,12 +342,41 @@ declare class TradingHandlers {
|
|
|
253
342
|
* net. Quote response surfaces both `estimatedOutputAmount` (gross)
|
|
254
343
|
* and `outputNet` so the FE can display reality.
|
|
255
344
|
*
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
* `request.userAddress`. See SDK_CORE_TRADING_AUDIT.md C6.
|
|
345
|
+
* `authenticatedAddress` first param: caller (issuer controller / FE
|
|
346
|
+
* proxy) MUST pass the address extracted from the verified
|
|
347
|
+
* session/JWT. Handler asserts it equals `request.userAddress`.
|
|
260
348
|
*/
|
|
261
349
|
handleSwap(authenticatedAddress: Address, request: ApiSwapRequest): Promise<ApiSwapResponse>;
|
|
350
|
+
/**
|
|
351
|
+
* Quote the input required to receive `request.amount` of the output
|
|
352
|
+
* token via Uniswap V4. Input-side operator fee is auto-quoted, so
|
|
353
|
+
* `inputGross = estimatedInputAmount + feeAmountInput` is the total
|
|
354
|
+
* the user must hold.
|
|
355
|
+
*
|
|
356
|
+
* Returns `quoteError: "QUOTE_UNAVAILABLE"` rather than throwing when
|
|
357
|
+
* no path exists.
|
|
358
|
+
*/
|
|
359
|
+
handleQuoteExactOut(request: ApiQuoteExactOutRequest): Promise<ApiQuoteExactOutResponse>;
|
|
360
|
+
/**
|
|
361
|
+
* Build a V4 exact-output swap UserOp.
|
|
362
|
+
*
|
|
363
|
+
* Quotes the best exact-output route, applies slippage as a CEILING on
|
|
364
|
+
* `maxAmountIn` (so the cap is never silently tightened by floor
|
|
365
|
+
* division), then encodes a 4-step batch:
|
|
366
|
+
*
|
|
367
|
+
* inputToken.transfer(feeRecipient, gasFeeAmountInput) [if > 0]
|
|
368
|
+
* → input.approve(Permit2, maxAmountIn)
|
|
369
|
+
* → Permit2.approve(router, maxAmountIn)
|
|
370
|
+
* → UniversalRouter.execute (V4 SWAP_EXACT_OUT)
|
|
371
|
+
*
|
|
372
|
+
* Operator fee is INPUT-token-side (charged before swap) so the user
|
|
373
|
+
* receives exactly `request.amount` of output.
|
|
374
|
+
*
|
|
375
|
+
* `authenticatedAddress` first param: caller MUST pass the address
|
|
376
|
+
* extracted from the verified session/JWT. Handler asserts equality
|
|
377
|
+
* with `request.userAddress`.
|
|
378
|
+
*/
|
|
379
|
+
handleSwapExactOut(authenticatedAddress: Address, request: ApiSwapExactOutRequest): Promise<ApiSwapExactOutResponse>;
|
|
262
380
|
/**
|
|
263
381
|
* Build an Orderly perp deposit UserOp.
|
|
264
382
|
*
|
|
@@ -290,6 +408,8 @@ declare function buildErc20ApprovalCalldata(spender: Address, amount: bigint): H
|
|
|
290
408
|
*/
|
|
291
409
|
declare function buildPermit2ApprovalCalldata(token: Address, spender: Address, amount: bigint, expiration: number): Hex;
|
|
292
410
|
|
|
411
|
+
declare const SWAP_EXACT_OUT_SINGLE: 8;
|
|
412
|
+
declare const SWAP_EXACT_OUT: 9;
|
|
293
413
|
/**
|
|
294
414
|
* Build the calldata inputs[0] (the V4_SWAP command payload) for
|
|
295
415
|
* UniversalRouter.execute.
|
|
@@ -308,22 +428,33 @@ declare function buildUniversalRouterExecuteArgs(currencyIn: Address, path: Path
|
|
|
308
428
|
inputs: Hex[];
|
|
309
429
|
};
|
|
310
430
|
/**
|
|
311
|
-
* Build
|
|
431
|
+
* Build the calldata inputs[0] (the V4_SWAP command payload) for
|
|
432
|
+
* UniversalRouter.execute, using the V4 exact-output flow.
|
|
312
433
|
*
|
|
313
|
-
*
|
|
314
|
-
* ready-to-use `{ commands, inputs }` for `UniversalRouter.execute`.
|
|
434
|
+
* Actions encoded: SWAP_EXACT_OUT → SETTLE_ALL → TAKE_ALL
|
|
315
435
|
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
436
|
+
* Settle/take semantics flip vs. the exact-input builder:
|
|
437
|
+
* - SETTLE_ALL caps the input pulled at `maxAmountIn` (router pulls
|
|
438
|
+
* only the actual amount the swap consumed; reverts if it exceeds
|
|
439
|
+
* the cap).
|
|
440
|
+
* - TAKE_ALL requires the user to receive *exactly* `amountOut` of
|
|
441
|
+
* `outputCurrency`.
|
|
321
442
|
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
443
|
+
* The `path` argument here is in V4 exact-output orientation — i.e.
|
|
444
|
+
* traversed output→input — which is what `findBestQuoteExactOut`
|
|
445
|
+
* (and `buildAllPaths(pools, tokenOut, tokenIn, ...)`) returns.
|
|
446
|
+
*
|
|
447
|
+
* @throws if `amountOut` or `maxAmountIn` exceeds 2^128 - 1.
|
|
448
|
+
*/
|
|
449
|
+
declare function buildV4SwapInputExactOut(currencyOut: Address, path: PathKey[], amountOut: bigint, maxAmountIn: bigint, inputCurrency: Address): Hex;
|
|
450
|
+
/**
|
|
451
|
+
* Build the full commands + inputs args for UniversalRouter.execute,
|
|
452
|
+
* using the V4 exact-output flow.
|
|
326
453
|
*/
|
|
454
|
+
declare function buildUniversalRouterExecuteArgsExactOut(currencyOut: Address, path: PathKey[], amountOut: bigint, maxAmountIn: bigint, inputCurrency: Address): {
|
|
455
|
+
commands: Hex;
|
|
456
|
+
inputs: Hex[];
|
|
457
|
+
};
|
|
327
458
|
declare function buildSwapFromQuote(params: {
|
|
328
459
|
quote: QuoteResult;
|
|
329
460
|
currencyIn: Address;
|
|
@@ -452,6 +583,80 @@ interface BuildSwapUserOpParams {
|
|
|
452
583
|
* negative, `swapPath` is empty, or `minAmountOut < gasFeeAmountOutput`.
|
|
453
584
|
*/
|
|
454
585
|
declare function buildSwapUserOp(params: BuildSwapUserOpParams): PartialUserOperation;
|
|
586
|
+
/**
|
|
587
|
+
* Parameters for `buildSwapUserOpExactOut`.
|
|
588
|
+
*
|
|
589
|
+
* @remarks
|
|
590
|
+
* The user must hold **`maxAmountIn + gasFeeAmountInput`** of
|
|
591
|
+
* `inputTokenAddress` before this UserOp executes — the operator-fee
|
|
592
|
+
* transfer is pre-swap, so it cannot be paid from swap proceeds.
|
|
593
|
+
*/
|
|
594
|
+
interface BuildSwapUserOpExactOutParams {
|
|
595
|
+
/** User's EOA (with EIP-7702 delegation to BatchExecutor). */
|
|
596
|
+
userAddress: Address;
|
|
597
|
+
/** ERC-4337 account nonce — fetched from EntryPoint by the caller. */
|
|
598
|
+
aaNonce: bigint;
|
|
599
|
+
/** Token being spent — approved to Permit2 + UniversalRouter. */
|
|
600
|
+
inputTokenAddress: Address;
|
|
601
|
+
/** Token user receives (exactly `amountOut` of). */
|
|
602
|
+
outputTokenAddress: Address;
|
|
603
|
+
/** UniversalRouter contract address (chain-specific). */
|
|
604
|
+
universalRouterAddress: Address;
|
|
605
|
+
/** Exact OUTPUT token amount the user wants to receive. */
|
|
606
|
+
amountOut: bigint;
|
|
607
|
+
/**
|
|
608
|
+
* Maximum INPUT token amount the user is willing to spend on the swap
|
|
609
|
+
* (slippage cap). The Permit2 approval covers this amount; the swap
|
|
610
|
+
* settles only the actual amount consumed.
|
|
611
|
+
*/
|
|
612
|
+
maxAmountIn: bigint;
|
|
613
|
+
/**
|
|
614
|
+
* V4 pool path in **output→input** orientation. Single-hop = 1 PathKey,
|
|
615
|
+
* multi-hop = N. Get this from `findBestQuoteExactOut().bestRoute.path`.
|
|
616
|
+
*/
|
|
617
|
+
swapPath: PathKey[];
|
|
618
|
+
/** Unix seconds. After this, the router rejects the swap. */
|
|
619
|
+
deadline: bigint;
|
|
620
|
+
/**
|
|
621
|
+
* Operator gas-reimbursement fee — paid in INPUT token, transferred
|
|
622
|
+
* BEFORE the swap. Omitted from the batch when 0n.
|
|
623
|
+
*
|
|
624
|
+
* Charged input-side rather than output-side because exact-output
|
|
625
|
+
* promises the user a precise output amount; deducting from output
|
|
626
|
+
* would silently break that promise. Mirrors the v0.3 input-side fee
|
|
627
|
+
* pattern used by perp-deposit.
|
|
628
|
+
*/
|
|
629
|
+
gasFeeAmountInput: bigint;
|
|
630
|
+
/**
|
|
631
|
+
* Where the gas fee lands — typically the canonical PAFI fee
|
|
632
|
+
* recipient from `getContractAddresses(chainId).pafiFeeRecipient`.
|
|
633
|
+
*/
|
|
634
|
+
feeRecipient: Address;
|
|
635
|
+
/** Override ERC-4337 gas estimates. Defaults are conservative. */
|
|
636
|
+
gasLimits?: {
|
|
637
|
+
callGasLimit?: bigint;
|
|
638
|
+
verificationGasLimit?: bigint;
|
|
639
|
+
preVerificationGas?: bigint;
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Build an unsigned UserOp for the V4 exact-output swap flow.
|
|
644
|
+
*
|
|
645
|
+
* UserOp shape (atomic batch via EIP-7702 BatchExecutor):
|
|
646
|
+
*
|
|
647
|
+
* 1. `inputToken.transfer(feeRecipient, gasFeeAmountInput)` — operator
|
|
648
|
+
* gas reimbursement, paid in INPUT token (omitted when 0).
|
|
649
|
+
* 2. `inputToken.approve(Permit2, maxAmountIn)` — cap, not exact.
|
|
650
|
+
* 3. `Permit2.approve(inputToken, router, maxAmountIn, deadline)` —
|
|
651
|
+
* Permit2 authorization to UniversalRouter for up to `maxAmountIn`.
|
|
652
|
+
* 4. `UniversalRouter.execute(commands, inputs, deadline)` — V4
|
|
653
|
+
* exact-output swap; user receives exactly `amountOut`.
|
|
654
|
+
*
|
|
655
|
+
* @throws when `amountOut`/`maxAmountIn` are non-positive,
|
|
656
|
+
* `gasFeeAmountInput` is negative, `swapPath` is empty, or `deadline`
|
|
657
|
+
* is out of Permit2's uint48 range.
|
|
658
|
+
*/
|
|
659
|
+
declare function buildSwapUserOpExactOut(params: BuildSwapUserOpExactOutParams): PartialUserOperation;
|
|
455
660
|
|
|
456
661
|
/**
|
|
457
662
|
* Combine point-token-specific pools and common pools for a given chain.
|
|
@@ -507,5 +712,322 @@ declare function quoteBestRoute(client: PublicClient, quoterAddress: Address, ex
|
|
|
507
712
|
* @param maxHops - Maximum number of hops per path (default 3)
|
|
508
713
|
*/
|
|
509
714
|
declare function findBestQuote(client: PublicClient, chainId: number, tokenIn: Address, tokenOut: Address, exactAmount: bigint, pools?: PoolKey[], quoterAddress?: Address, maxHops?: number): Promise<BestQuote>;
|
|
715
|
+
/**
|
|
716
|
+
* Quote V4 exact-output for a multi-hop path.
|
|
717
|
+
*
|
|
718
|
+
* @param exactCurrency - The OUTPUT token (the one the user wants to
|
|
719
|
+
* receive a precise amount of).
|
|
720
|
+
* @param path - PathKey[] in output→input orientation. Use
|
|
721
|
+
* `buildAllPaths(pools, tokenOut, tokenIn, ...)`
|
|
722
|
+
* (arguments swapped vs. exact-in) to produce
|
|
723
|
+
* the right shape.
|
|
724
|
+
* @param exactAmount - Exact OUTPUT amount the user wants.
|
|
725
|
+
* @returns `{ amountIn, gasEstimate, path }` — the input amount required
|
|
726
|
+
* to receive `exactAmount` of `exactCurrency`.
|
|
727
|
+
*/
|
|
728
|
+
declare function quoteExactOutput(client: PublicClient, quoterAddress: Address, exactCurrency: Address, path: PathKey[], exactAmount: bigint): Promise<ExactOutputQuoteResult>;
|
|
729
|
+
/**
|
|
730
|
+
* Quote V4 exact-output for a single-hop swap, given an explicit PoolKey
|
|
731
|
+
* and direction.
|
|
732
|
+
*
|
|
733
|
+
* `zeroForOne` semantics are identical to the exact-input variant —
|
|
734
|
+
* "trade direction" is invariant to the exactness parameter. Only
|
|
735
|
+
* `exactAmount` flips meaning (here: amount of *output* currency the
|
|
736
|
+
* user wants to receive).
|
|
737
|
+
*/
|
|
738
|
+
declare function quoteExactOutputSingle(client: PublicClient, quoterAddress: Address, poolKey: PoolKey, zeroForOne: boolean, exactAmount: bigint, hookData: `0x${string}`): Promise<{
|
|
739
|
+
amountIn: bigint;
|
|
740
|
+
gasEstimate: bigint;
|
|
741
|
+
}>;
|
|
742
|
+
/**
|
|
743
|
+
* Try multiple PathKey[] routes for an exact-output swap and return the
|
|
744
|
+
* route requiring the **smallest** input amount, plus all results.
|
|
745
|
+
* Routes that fail (e.g. pool does not exist) are silently skipped.
|
|
746
|
+
*
|
|
747
|
+
* Uses viem multicall to batch all quotes into a single RPC call.
|
|
748
|
+
*/
|
|
749
|
+
declare function quoteBestRouteExactOut(client: PublicClient, quoterAddress: Address, exactCurrency: Address, routes: PathKey[][], exactAmount: bigint): Promise<ExactOutputBestQuote>;
|
|
750
|
+
/**
|
|
751
|
+
* Find and quote the best V4 exact-output route from `tokenIn` to
|
|
752
|
+
* `tokenOut` for a desired output amount.
|
|
753
|
+
*
|
|
754
|
+
* Symmetric to `findBestQuote` but with two key differences:
|
|
755
|
+
*
|
|
756
|
+
* - `exactAmount` is denominated in `tokenOut` (the OUTPUT token).
|
|
757
|
+
* - Internally calls `buildAllPaths(allPools, tokenOut, tokenIn, ...)`
|
|
758
|
+
* (arguments swapped) to enumerate paths in output→input
|
|
759
|
+
* orientation, which is what `quoteExactOutput` expects.
|
|
760
|
+
*
|
|
761
|
+
* @param client - viem PublicClient.
|
|
762
|
+
* @param chainId - Chain ID (looks up COMMON_POOLS + V4_QUOTER_ADDRESSES).
|
|
763
|
+
* @param tokenIn - Input token address (what user pays).
|
|
764
|
+
* @param tokenOut - Output token address (what user wants exactly).
|
|
765
|
+
* @param exactAmount - Exact OUTPUT amount.
|
|
766
|
+
* @param pools - Additional pools (e.g. point-token-specific).
|
|
767
|
+
* @param quoterAddress - Override the default V4 Quoter address.
|
|
768
|
+
* @param maxHops - Maximum number of hops per path (default 3).
|
|
769
|
+
*/
|
|
770
|
+
declare function findBestQuoteExactOut(client: PublicClient, chainId: number, tokenIn: Address, tokenOut: Address, exactAmount: bigint, pools?: PoolKey[], quoterAddress?: Address, maxHops?: number): Promise<ExactOutputBestQuote>;
|
|
771
|
+
|
|
772
|
+
interface SwapDirectParams {
|
|
773
|
+
/** User EOA — must be delegated via EIP-7702 to a PAFI-supported impl. */
|
|
774
|
+
userAddress: Address;
|
|
775
|
+
chainId: number;
|
|
776
|
+
inputTokenAddress: Address;
|
|
777
|
+
outputTokenAddress: Address;
|
|
778
|
+
/** Input amount (raw token decimals). */
|
|
779
|
+
amount: bigint;
|
|
780
|
+
/** Pools to route through. Caller pre-fetches via `fetchPafiPools`. */
|
|
781
|
+
pools?: PoolKey[];
|
|
782
|
+
publicClient: PublicClient;
|
|
783
|
+
walletClient: WalletClient;
|
|
784
|
+
/**
|
|
785
|
+
* Slippage tolerance in basis points. Default 50 single-hop / 100
|
|
786
|
+
* multi-hop (handler picks based on `bestRoute.path.length`).
|
|
787
|
+
*/
|
|
788
|
+
slippageBps?: number;
|
|
789
|
+
/** Swap deadline (unix seconds). Default = now + 5 minutes. */
|
|
790
|
+
deadline?: bigint;
|
|
791
|
+
/**
|
|
792
|
+
* Operator fee in OUTPUT token, paid to PAFI fee recipient.
|
|
793
|
+
*
|
|
794
|
+
* - `undefined` (default for direct path): **skip the fee transfer
|
|
795
|
+
* entirely** — PAFI is not sponsoring this swap, no reimbursement
|
|
796
|
+
* owed. Most callers want this.
|
|
797
|
+
* - `0n` — same as above, explicit.
|
|
798
|
+
* - explicit `bigint` — include the fee transfer (rare; only when
|
|
799
|
+
* issuer dev/test wants to mirror sponsored behaviour).
|
|
800
|
+
*/
|
|
801
|
+
gasFeeAmountOutput?: bigint;
|
|
802
|
+
/** Wait for receipt before returning. Default `true`. */
|
|
803
|
+
waitForReceipt?: boolean;
|
|
804
|
+
onWarning?: (msg: string) => void;
|
|
805
|
+
}
|
|
806
|
+
interface SwapDirectResult {
|
|
807
|
+
txHash: Hex;
|
|
808
|
+
receipt?: TransactionReceipt;
|
|
809
|
+
estimatedOutputAmount: bigint;
|
|
810
|
+
minAmountOut: bigint;
|
|
811
|
+
hops: number;
|
|
812
|
+
deadline: bigint;
|
|
813
|
+
feeAmountUsed: bigint;
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* One-shot helper for the **FE-direct swap** path — no AA, no bundler,
|
|
817
|
+
* no PAFI sponsor-relayer. The user EOA pays gas in ETH and broadcasts
|
|
818
|
+
* a single type-2 transaction calling its own EIP-7702 delegated
|
|
819
|
+
* bytecode (`Simple7702Account.executeBatch`).
|
|
820
|
+
*
|
|
821
|
+
* Flow:
|
|
822
|
+
* 1. Verify the EOA has EIP-7702 delegation to a PAFI-supported impl
|
|
823
|
+
* (Simple7702Account or Coinbase SW v2 BatchExecutor). Throw with
|
|
824
|
+
* a clear hint pointing at `delegateDirect()` if not delegated.
|
|
825
|
+
* 2. `findBestQuote` → best route + gross output.
|
|
826
|
+
* 3. `buildSwapUserOp` → encoded `executeBatch(calls)` calldata.
|
|
827
|
+
* 4. `walletClient.sendTransaction({ to: userAddress, data: callData })`
|
|
828
|
+
* — self-call into the delegated bytecode, which dispatches the
|
|
829
|
+
* batch (input.approve → Permit2.approve → UR.execute → optional
|
|
830
|
+
* fee transfer).
|
|
831
|
+
* 5. Wait for receipt (optional).
|
|
832
|
+
*
|
|
833
|
+
* Use when:
|
|
834
|
+
* - The FE doesn't have a Pimlico API key + doesn't want to depend on
|
|
835
|
+
* PAFI sponsor-relayer.
|
|
836
|
+
* - The user already has a small ETH balance.
|
|
837
|
+
* - You need a deterministic, single-tx swap (vs. AA UserOp's longer
|
|
838
|
+
* bundler round-trip).
|
|
839
|
+
*
|
|
840
|
+
* Throws when the user is NOT yet delegated — caller should run
|
|
841
|
+
* `delegateDirect` first or use the AA path (`TradingHandlers.handleSwap`
|
|
842
|
+
* + `permissionless`).
|
|
843
|
+
*
|
|
844
|
+
* @example
|
|
845
|
+
* ```ts
|
|
846
|
+
* import { swapDirect, fetchPafiPools } from "@pafi-dev/trading";
|
|
847
|
+
*
|
|
848
|
+
* const pools = await fetchPafiPools(8453, POINT_TOKEN);
|
|
849
|
+
* const result = await swapDirect({
|
|
850
|
+
* userAddress: wallet.address,
|
|
851
|
+
* chainId: 8453,
|
|
852
|
+
* inputTokenAddress: POINT_TOKEN,
|
|
853
|
+
* outputTokenAddress: USDT,
|
|
854
|
+
* amount: parseUnits("100", 18),
|
|
855
|
+
* pools,
|
|
856
|
+
* publicClient,
|
|
857
|
+
* walletClient,
|
|
858
|
+
* });
|
|
859
|
+
* console.log("Swap tx:", result.txHash);
|
|
860
|
+
* ```
|
|
861
|
+
*/
|
|
862
|
+
declare function swapDirect(params: SwapDirectParams): Promise<SwapDirectResult>;
|
|
863
|
+
|
|
864
|
+
interface SwapDirectExactOutParams {
|
|
865
|
+
/** User EOA — must be delegated via EIP-7702 to a PAFI-supported impl. */
|
|
866
|
+
userAddress: Address;
|
|
867
|
+
chainId: number;
|
|
868
|
+
inputTokenAddress: Address;
|
|
869
|
+
outputTokenAddress: Address;
|
|
870
|
+
/** Exact OUTPUT amount the user wants to receive (raw token decimals). */
|
|
871
|
+
amount: bigint;
|
|
872
|
+
/** Pools to route through. Caller pre-fetches via `fetchPafiPools`. */
|
|
873
|
+
pools?: PoolKey[];
|
|
874
|
+
publicClient: PublicClient;
|
|
875
|
+
walletClient: WalletClient;
|
|
876
|
+
/**
|
|
877
|
+
* Slippage tolerance in basis points. Default 50 single-hop / 100
|
|
878
|
+
* multi-hop. Slippage is applied as a CEILING on `maxAmountIn`.
|
|
879
|
+
*/
|
|
880
|
+
slippageBps?: number;
|
|
881
|
+
/** Swap deadline (unix seconds). Default = now + 5 minutes. */
|
|
882
|
+
deadline?: bigint;
|
|
883
|
+
/**
|
|
884
|
+
* Operator fee in INPUT token, paid to PAFI fee recipient.
|
|
885
|
+
*
|
|
886
|
+
* - `undefined` (default for direct path): **skip the fee transfer
|
|
887
|
+
* entirely** — PAFI is not sponsoring this swap, no reimbursement
|
|
888
|
+
* owed. Most callers want this.
|
|
889
|
+
* - `0n` — same as above, explicit.
|
|
890
|
+
* - explicit `bigint` — include the fee transfer (rare; only when
|
|
891
|
+
* issuer dev/test wants to mirror sponsored behaviour).
|
|
892
|
+
*/
|
|
893
|
+
gasFeeAmountInput?: bigint;
|
|
894
|
+
/** Wait for receipt before returning. Default `true`. */
|
|
895
|
+
waitForReceipt?: boolean;
|
|
896
|
+
onWarning?: (msg: string) => void;
|
|
897
|
+
}
|
|
898
|
+
interface SwapDirectExactOutResult {
|
|
899
|
+
txHash: Hex;
|
|
900
|
+
receipt?: TransactionReceipt;
|
|
901
|
+
/** Echoes `params.amount` — the exact output. */
|
|
902
|
+
outputAmount: bigint;
|
|
903
|
+
/** Raw input amount from the V4 quoter, before slippage. */
|
|
904
|
+
estimatedInputAmount: bigint;
|
|
905
|
+
/** Slippage-bumped cap on input — encoded in the swap calldata. */
|
|
906
|
+
maxAmountIn: bigint;
|
|
907
|
+
hops: number;
|
|
908
|
+
deadline: bigint;
|
|
909
|
+
feeAmountUsed: bigint;
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* One-shot helper for the **FE-direct exact-output swap** path — no AA,
|
|
913
|
+
* no bundler, no PAFI sponsor-relayer. Symmetric to `swapDirect` but
|
|
914
|
+
* specifies the OUTPUT amount and bumps slippage UPWARD on `maxAmountIn`.
|
|
915
|
+
*
|
|
916
|
+
* Caller pre-conditions:
|
|
917
|
+
*
|
|
918
|
+
* - User EOA already has EIP-7702 delegation (`delegateDirect` first).
|
|
919
|
+
* - User EOA holds **`maxAmountIn + gasFeeAmountInput`** of
|
|
920
|
+
* `inputTokenAddress` (not just `amount` — that's output).
|
|
921
|
+
*
|
|
922
|
+
* Flow:
|
|
923
|
+
* 1. Verify the EOA has EIP-7702 delegation to a PAFI-supported impl.
|
|
924
|
+
* 2. `findBestQuoteExactOut` → best route + required input.
|
|
925
|
+
* 3. Slippage ceiling → `maxAmountIn`.
|
|
926
|
+
* 4. `buildSwapUserOpExactOut` → encoded `executeBatch(calls)` calldata.
|
|
927
|
+
* 5. `walletClient.sendTransaction({ to: userAddress, data: callData })`.
|
|
928
|
+
* 6. Wait for receipt (optional).
|
|
929
|
+
*
|
|
930
|
+
* @example
|
|
931
|
+
* ```ts
|
|
932
|
+
* import { swapDirectExactOut, fetchPafiPools } from "@pafi-dev/trading";
|
|
933
|
+
*
|
|
934
|
+
* const pools = await fetchPafiPools(8453, POINT_TOKEN);
|
|
935
|
+
* const result = await swapDirectExactOut({
|
|
936
|
+
* userAddress: wallet.address,
|
|
937
|
+
* chainId: 8453,
|
|
938
|
+
* inputTokenAddress: POINT_TOKEN,
|
|
939
|
+
* outputTokenAddress: USDT,
|
|
940
|
+
* amount: parseUnits("50", 6), // exactly 50 USDT
|
|
941
|
+
* pools,
|
|
942
|
+
* publicClient,
|
|
943
|
+
* walletClient,
|
|
944
|
+
* });
|
|
945
|
+
* console.log("Swap tx:", result.txHash);
|
|
946
|
+
* ```
|
|
947
|
+
*/
|
|
948
|
+
declare function swapDirectExactOut(params: SwapDirectExactOutParams): Promise<SwapDirectExactOutResult>;
|
|
949
|
+
|
|
950
|
+
interface PerpDepositDirectParams {
|
|
951
|
+
/** User EOA — must be EIP-7702 delegated. */
|
|
952
|
+
userAddress: Address;
|
|
953
|
+
chainId: number;
|
|
954
|
+
/** USDC amount to deposit (6-decimal raw units). */
|
|
955
|
+
amount: bigint;
|
|
956
|
+
/** Orderly broker — `'orderly' | 'woofi_pro' | 'logx'`. */
|
|
957
|
+
brokerId: keyof typeof BROKER_HASHES;
|
|
958
|
+
publicClient: PublicClient;
|
|
959
|
+
walletClient: WalletClient;
|
|
960
|
+
/**
|
|
961
|
+
* Max acceptable USDC fee charged by the Relay (slippage cap on its
|
|
962
|
+
* USD-pricing of `msg.value`). Default `max(amount * 5%, 2 USDC)` —
|
|
963
|
+
* matches `TradingHandlers.handlePerpDeposit`.
|
|
964
|
+
*/
|
|
965
|
+
maxRelayFee?: bigint;
|
|
966
|
+
/**
|
|
967
|
+
* Operator fee in USDC (input-token, BEFORE deposit). Same semantics
|
|
968
|
+
* as `swapDirect.gasFeeAmountOutput`:
|
|
969
|
+
*
|
|
970
|
+
* - `undefined` (default for direct path): **skip the fee transfer**
|
|
971
|
+
* — PAFI is not sponsoring this deposit.
|
|
972
|
+
* - explicit `bigint` — include the fee transfer.
|
|
973
|
+
*/
|
|
974
|
+
gasFeeUsdc?: bigint;
|
|
975
|
+
/** Wait for receipt before returning. Default `true`. */
|
|
976
|
+
waitForReceipt?: boolean;
|
|
977
|
+
onWarning?: (msg: string) => void;
|
|
978
|
+
}
|
|
979
|
+
interface PerpDepositDirectResult {
|
|
980
|
+
txHash: Hex;
|
|
981
|
+
receipt?: TransactionReceipt;
|
|
982
|
+
/** Resolved USDC fee charged by the Relay. */
|
|
983
|
+
relayTokenFee: bigint;
|
|
984
|
+
/** Cap applied to the Relay fee (slippage allowance). */
|
|
985
|
+
maxFee: bigint;
|
|
986
|
+
/** USDC reaching Orderly Vault after Relay's fee = amount - relayTokenFee. */
|
|
987
|
+
netDeposit: bigint;
|
|
988
|
+
/** Operator fee actually included (0n on default direct path). */
|
|
989
|
+
feeAmountUsed: bigint;
|
|
990
|
+
accountId: Hex;
|
|
991
|
+
brokerHash: Hex;
|
|
992
|
+
usdcAddress: Address;
|
|
993
|
+
relayAddress: Address;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* One-shot helper for the **FE-direct perp deposit** path — no AA, no
|
|
997
|
+
* bundler, no PAFI sponsor-relayer. The user EOA pays gas in ETH and
|
|
998
|
+
* broadcasts a single type-2 transaction calling its own EIP-7702
|
|
999
|
+
* delegated bytecode (`Simple7702Account.executeBatch`).
|
|
1000
|
+
*
|
|
1001
|
+
* Flow:
|
|
1002
|
+
* 1. Verify EIP-7702 delegation (same precondition as `swapDirect`).
|
|
1003
|
+
* 2. Resolve USDC + verify broker is whitelisted on Orderly Vault.
|
|
1004
|
+
* 3. Quote `Relay.tokenFee` for the deposit; compute `netDeposit`.
|
|
1005
|
+
* 4. `buildPerpDepositViaRelay` → encoded `executeBatch(calls)`
|
|
1006
|
+
* (USDC.approve(relay) + Relay.deposit + optional fee transfer).
|
|
1007
|
+
* 5. `walletClient.sendTransaction({ to: userAddress, data: callData })`.
|
|
1008
|
+
* 6. Wait for receipt (optional).
|
|
1009
|
+
*
|
|
1010
|
+
* Use when: same conditions as `swapDirect` — FE doesn't have Pimlico
|
|
1011
|
+
* key, doesn't want sponsor-relayer dependency, user has small ETH.
|
|
1012
|
+
*
|
|
1013
|
+
* Throws when the user is NOT yet delegated.
|
|
1014
|
+
*
|
|
1015
|
+
* @example
|
|
1016
|
+
* ```ts
|
|
1017
|
+
* import { perpDepositDirect } from "@pafi-dev/trading";
|
|
1018
|
+
*
|
|
1019
|
+
* const result = await perpDepositDirect({
|
|
1020
|
+
* userAddress: wallet.address,
|
|
1021
|
+
* chainId: 8453,
|
|
1022
|
+
* amount: parseUnits("10", 6), // 10 USDC
|
|
1023
|
+
* brokerId: "orderly",
|
|
1024
|
+
* publicClient,
|
|
1025
|
+
* walletClient,
|
|
1026
|
+
* });
|
|
1027
|
+
* console.log("Deposit tx:", result.txHash);
|
|
1028
|
+
* console.log("Net deposit to Orderly:", result.netDeposit, "USDC raw");
|
|
1029
|
+
* ```
|
|
1030
|
+
*/
|
|
1031
|
+
declare function perpDepositDirect(params: PerpDepositDirectParams): Promise<PerpDepositDirectResult>;
|
|
510
1032
|
|
|
511
|
-
export { type ApiPerpDepositRequest, type ApiPerpDepositResponse, type ApiQuoteError, type ApiQuoteRequest, type ApiQuoteResponse, type ApiSwapRequest, type ApiSwapResponse, type BuildSwapUserOpParams, type SwapSimulationResult, TradingHandlers, type TradingHandlersConfig, buildAllPaths, buildErc20ApprovalCalldata, buildPermit2ApprovalCalldata, buildSwapFromQuote, buildSwapUserOp, buildUniversalRouterExecuteArgs, buildV4SwapInput, checkAllowance, combineRoutes, findBestQuote, quoteBestRoute, quoteExactInput, quoteExactInputSingle, simulateSwap };
|
|
1033
|
+
export { type ApiPerpDepositRequest, type ApiPerpDepositResponse, type ApiQuoteError, type ApiQuoteExactOutRequest, type ApiQuoteExactOutResponse, type ApiQuoteRequest, type ApiQuoteResponse, type ApiSwapExactOutRequest, type ApiSwapExactOutResponse, type ApiSwapRequest, type ApiSwapResponse, type BuildSwapUserOpExactOutParams, type BuildSwapUserOpParams, type PerpDepositDirectParams, type PerpDepositDirectResult, SWAP_EXACT_OUT, SWAP_EXACT_OUT_SINGLE, type SwapDirectExactOutParams, type SwapDirectExactOutResult, type SwapDirectParams, type SwapDirectResult, type SwapSimulationResult, TradingHandlers, type TradingHandlersConfig, buildAllPaths, buildErc20ApprovalCalldata, buildPermit2ApprovalCalldata, buildSwapFromQuote, buildSwapUserOp, buildSwapUserOpExactOut, buildUniversalRouterExecuteArgs, buildUniversalRouterExecuteArgsExactOut, buildV4SwapInput, buildV4SwapInputExactOut, checkAllowance, combineRoutes, findBestQuote, findBestQuoteExactOut, perpDepositDirect, quoteBestRoute, quoteBestRouteExactOut, quoteExactInput, quoteExactInputSingle, quoteExactOutput, quoteExactOutputSingle, simulateSwap, swapDirect, swapDirectExactOut };
|