@pafi-dev/trading 0.1.10 → 0.2.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 +132 -378
- package/dist/index.cjs +408 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +269 -46
- package/dist/index.d.ts +269 -46
- package/dist/index.js +378 -36
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
// src/api/handlers.ts
|
|
2
2
|
import { getAddress } from "viem";
|
|
3
3
|
import {
|
|
4
|
-
findBestQuote,
|
|
5
|
-
buildSwapWithGasDeduction,
|
|
6
4
|
buildPerpDepositWithGasDeduction,
|
|
7
5
|
buildPerpDepositViaRelay,
|
|
8
6
|
ORDERLY_RELAY_ABI,
|
|
@@ -15,6 +13,329 @@ import {
|
|
|
15
13
|
computeAccountId,
|
|
16
14
|
quoteOperatorFeePt
|
|
17
15
|
} from "@pafi-dev/core";
|
|
16
|
+
|
|
17
|
+
// src/quoting/routes.ts
|
|
18
|
+
import { COMMON_POOLS, POINT_TOKEN_POOLS } from "@pafi-dev/core";
|
|
19
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
20
|
+
function combineRoutes(chainId, pointTokenAddress) {
|
|
21
|
+
const commonPools = COMMON_POOLS[chainId] ?? [];
|
|
22
|
+
const pointPools = POINT_TOKEN_POOLS[chainId]?.[pointTokenAddress] ?? [];
|
|
23
|
+
return [...pointPools, ...commonPools];
|
|
24
|
+
}
|
|
25
|
+
function buildAllPaths(pools, tokenIn, tokenOut, maxHops = 3) {
|
|
26
|
+
const results = [];
|
|
27
|
+
function dfs(currentToken, currentPath, usedPoolIndices) {
|
|
28
|
+
if (currentPath.length > maxHops) return;
|
|
29
|
+
if (currentPath.length > 0 && currentToken.toLowerCase() === tokenOut.toLowerCase()) {
|
|
30
|
+
results.push([...currentPath]);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
for (let i = 0; i < pools.length; i++) {
|
|
34
|
+
if (usedPoolIndices.has(i)) continue;
|
|
35
|
+
const pool = pools[i];
|
|
36
|
+
const c0 = pool.currency0.toLowerCase();
|
|
37
|
+
const c1 = pool.currency1.toLowerCase();
|
|
38
|
+
const curr = currentToken.toLowerCase();
|
|
39
|
+
let nextToken = null;
|
|
40
|
+
if (curr === c0) {
|
|
41
|
+
nextToken = pool.currency1;
|
|
42
|
+
} else if (curr === c1) {
|
|
43
|
+
nextToken = pool.currency0;
|
|
44
|
+
}
|
|
45
|
+
if (!nextToken) continue;
|
|
46
|
+
const hop = {
|
|
47
|
+
intermediateCurrency: nextToken,
|
|
48
|
+
fee: pool.fee,
|
|
49
|
+
tickSpacing: pool.tickSpacing,
|
|
50
|
+
hooks: pool.hooks ?? ZERO_ADDRESS,
|
|
51
|
+
hookData: "0x"
|
|
52
|
+
};
|
|
53
|
+
usedPoolIndices.add(i);
|
|
54
|
+
currentPath.push(hop);
|
|
55
|
+
dfs(nextToken, currentPath, usedPoolIndices);
|
|
56
|
+
currentPath.pop();
|
|
57
|
+
usedPoolIndices.delete(i);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
dfs(tokenIn, [], /* @__PURE__ */ new Set());
|
|
61
|
+
return results;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/quoting/quote.ts
|
|
65
|
+
import { v4QuoterAbi } from "@pafi-dev/core";
|
|
66
|
+
import { COMMON_POOLS as COMMON_POOLS2, V4_QUOTER_ADDRESSES } from "@pafi-dev/core";
|
|
67
|
+
async function quoteExactInput(client, quoterAddress, exactCurrency, path, exactAmount) {
|
|
68
|
+
const [amountOut, gasEstimate] = await client.readContract({
|
|
69
|
+
address: quoterAddress,
|
|
70
|
+
abi: v4QuoterAbi,
|
|
71
|
+
functionName: "quoteExactInput",
|
|
72
|
+
args: [{ exactCurrency, path, exactAmount: BigInt(exactAmount) }]
|
|
73
|
+
});
|
|
74
|
+
return { amountOut, gasEstimate, path };
|
|
75
|
+
}
|
|
76
|
+
async function quoteExactInputSingle(client, quoterAddress, poolKey, zeroForOne, exactAmount, hookData) {
|
|
77
|
+
const [amountOut, gasEstimate] = await client.readContract({
|
|
78
|
+
address: quoterAddress,
|
|
79
|
+
abi: v4QuoterAbi,
|
|
80
|
+
functionName: "quoteExactInputSingle",
|
|
81
|
+
args: [
|
|
82
|
+
{
|
|
83
|
+
poolKey,
|
|
84
|
+
zeroForOne,
|
|
85
|
+
exactAmount: BigInt(exactAmount),
|
|
86
|
+
hookData
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
});
|
|
90
|
+
return { amountOut, gasEstimate };
|
|
91
|
+
}
|
|
92
|
+
async function quoteBestRoute(client, quoterAddress, exactCurrency, routes, exactAmount) {
|
|
93
|
+
const results = await client.multicall({
|
|
94
|
+
contracts: routes.map((path) => ({
|
|
95
|
+
address: quoterAddress,
|
|
96
|
+
abi: v4QuoterAbi,
|
|
97
|
+
functionName: "quoteExactInput",
|
|
98
|
+
args: [
|
|
99
|
+
{
|
|
100
|
+
exactCurrency,
|
|
101
|
+
path,
|
|
102
|
+
exactAmount: BigInt(exactAmount)
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
})),
|
|
106
|
+
allowFailure: true
|
|
107
|
+
});
|
|
108
|
+
const allRoutes = [];
|
|
109
|
+
for (let i = 0; i < results.length; i++) {
|
|
110
|
+
const r = results[i];
|
|
111
|
+
if (r.status === "success") {
|
|
112
|
+
const [amountOut, gasEstimate] = r.result;
|
|
113
|
+
allRoutes.push({ amountOut, gasEstimate, path: routes[i] });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (allRoutes.length === 0) {
|
|
117
|
+
throw new Error("No valid routes found");
|
|
118
|
+
}
|
|
119
|
+
const bestRoute = allRoutes.reduce(
|
|
120
|
+
(best, current) => current.amountOut > best.amountOut ? current : best
|
|
121
|
+
);
|
|
122
|
+
return { bestRoute, allRoutes };
|
|
123
|
+
}
|
|
124
|
+
async function findBestQuote(client, chainId, tokenIn, tokenOut, exactAmount, pools = [], quoterAddress, maxHops = 3) {
|
|
125
|
+
const quoter = quoterAddress ?? V4_QUOTER_ADDRESSES[chainId];
|
|
126
|
+
if (!quoter) {
|
|
127
|
+
throw new Error(`No V4 Quoter address configured for chain ${chainId}`);
|
|
128
|
+
}
|
|
129
|
+
const commonPools = COMMON_POOLS2[chainId] ?? [];
|
|
130
|
+
const allPools = [...pools, ...commonPools];
|
|
131
|
+
const paths = buildAllPaths(allPools, tokenIn, tokenOut, maxHops);
|
|
132
|
+
if (paths.length === 0) {
|
|
133
|
+
throw new Error(`No paths found from ${tokenIn} to ${tokenOut}`);
|
|
134
|
+
}
|
|
135
|
+
return quoteBestRoute(client, quoter, tokenIn, paths, exactAmount);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/swap/approval.ts
|
|
139
|
+
import { encodeFunctionData } from "viem";
|
|
140
|
+
import { erc20Abi } from "@pafi-dev/core";
|
|
141
|
+
import { permit2Abi } from "@pafi-dev/core";
|
|
142
|
+
async function checkAllowance(client, token, owner, spender) {
|
|
143
|
+
return client.readContract({
|
|
144
|
+
address: token,
|
|
145
|
+
abi: erc20Abi,
|
|
146
|
+
functionName: "allowance",
|
|
147
|
+
args: [owner, spender]
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function buildErc20ApprovalCalldata(spender, amount) {
|
|
151
|
+
return encodeFunctionData({
|
|
152
|
+
abi: erc20Abi,
|
|
153
|
+
functionName: "approve",
|
|
154
|
+
args: [spender, amount]
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
function buildPermit2ApprovalCalldata(token, spender, amount, expiration) {
|
|
158
|
+
return encodeFunctionData({
|
|
159
|
+
abi: permit2Abi,
|
|
160
|
+
functionName: "approve",
|
|
161
|
+
args: [token, spender, amount, expiration]
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/swap/universalRouter.ts
|
|
166
|
+
import { encodeAbiParameters, encodePacked } from "viem";
|
|
167
|
+
var V4_SWAP = 16;
|
|
168
|
+
var SWAP_EXACT_IN = 7;
|
|
169
|
+
var SETTLE_ALL = 12;
|
|
170
|
+
var TAKE_ALL = 15;
|
|
171
|
+
var PATH_KEY_ABI_COMPONENTS = [
|
|
172
|
+
{ name: "intermediateCurrency", type: "address" },
|
|
173
|
+
{ name: "fee", type: "uint256" },
|
|
174
|
+
{ name: "tickSpacing", type: "int24" },
|
|
175
|
+
{ name: "hooks", type: "address" },
|
|
176
|
+
{ name: "hookData", type: "bytes" }
|
|
177
|
+
];
|
|
178
|
+
var EXACT_INPUT_PARAMS_ABI = [
|
|
179
|
+
{ name: "currencyIn", type: "address" },
|
|
180
|
+
{
|
|
181
|
+
name: "path",
|
|
182
|
+
type: "tuple[]",
|
|
183
|
+
components: PATH_KEY_ABI_COMPONENTS
|
|
184
|
+
},
|
|
185
|
+
{ name: "amountIn", type: "uint128" },
|
|
186
|
+
{ name: "amountOutMinimum", type: "uint128" }
|
|
187
|
+
];
|
|
188
|
+
function buildV4SwapInput(currencyIn, path, amountIn, minAmountOut, outputCurrency) {
|
|
189
|
+
const actions = encodePacked(
|
|
190
|
+
["uint8", "uint8", "uint8"],
|
|
191
|
+
[SWAP_EXACT_IN, SETTLE_ALL, TAKE_ALL]
|
|
192
|
+
);
|
|
193
|
+
const swapParam = encodeAbiParameters(
|
|
194
|
+
[{ name: "swap", type: "tuple", components: EXACT_INPUT_PARAMS_ABI }],
|
|
195
|
+
[
|
|
196
|
+
{
|
|
197
|
+
currencyIn,
|
|
198
|
+
path: path.map((p) => ({
|
|
199
|
+
intermediateCurrency: p.intermediateCurrency,
|
|
200
|
+
fee: BigInt(p.fee),
|
|
201
|
+
tickSpacing: p.tickSpacing,
|
|
202
|
+
hooks: p.hooks,
|
|
203
|
+
hookData: p.hookData
|
|
204
|
+
})),
|
|
205
|
+
amountIn,
|
|
206
|
+
amountOutMinimum: minAmountOut
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
);
|
|
210
|
+
const settleParam = encodeAbiParameters(
|
|
211
|
+
[
|
|
212
|
+
{ name: "currency", type: "address" },
|
|
213
|
+
{ name: "maxAmount", type: "uint256" }
|
|
214
|
+
],
|
|
215
|
+
[currencyIn, amountIn]
|
|
216
|
+
);
|
|
217
|
+
const takeParam = encodeAbiParameters(
|
|
218
|
+
[
|
|
219
|
+
{ name: "currency", type: "address" },
|
|
220
|
+
{ name: "minAmount", type: "uint256" }
|
|
221
|
+
],
|
|
222
|
+
[outputCurrency, minAmountOut]
|
|
223
|
+
);
|
|
224
|
+
return encodeAbiParameters(
|
|
225
|
+
[
|
|
226
|
+
{ name: "actions", type: "bytes" },
|
|
227
|
+
{ name: "params", type: "bytes[]" }
|
|
228
|
+
],
|
|
229
|
+
[actions, [swapParam, settleParam, takeParam]]
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
function buildUniversalRouterExecuteArgs(currencyIn, path, amountIn, minAmountOut, outputCurrency) {
|
|
233
|
+
const commands = encodePacked(["uint8"], [V4_SWAP]);
|
|
234
|
+
const inputs = [
|
|
235
|
+
buildV4SwapInput(currencyIn, path, amountIn, minAmountOut, outputCurrency)
|
|
236
|
+
];
|
|
237
|
+
return { commands, inputs };
|
|
238
|
+
}
|
|
239
|
+
function buildSwapFromQuote(params) {
|
|
240
|
+
return buildUniversalRouterExecuteArgs(
|
|
241
|
+
params.currencyIn,
|
|
242
|
+
params.quote.path,
|
|
243
|
+
params.amountIn,
|
|
244
|
+
params.minAmountOut,
|
|
245
|
+
params.currencyOut
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/swap/simulate.ts
|
|
250
|
+
import { universalRouterAbi } from "@pafi-dev/core";
|
|
251
|
+
import { SimulationError } from "@pafi-dev/core";
|
|
252
|
+
async function simulateSwap(client, routerAddress, commands, inputs, deadline, from) {
|
|
253
|
+
try {
|
|
254
|
+
const gasEstimate = await client.estimateContractGas({
|
|
255
|
+
address: routerAddress,
|
|
256
|
+
abi: universalRouterAbi,
|
|
257
|
+
functionName: "execute",
|
|
258
|
+
args: [commands, inputs, deadline],
|
|
259
|
+
account: from
|
|
260
|
+
});
|
|
261
|
+
return { success: true, gasEstimate };
|
|
262
|
+
} catch (error) {
|
|
263
|
+
const message = error instanceof Error ? error.message : "Unknown simulation error";
|
|
264
|
+
throw new SimulationError("swap", message);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// src/swap/buildSwap.ts
|
|
269
|
+
import { encodeFunctionData as encodeFunctionData2 } from "viem";
|
|
270
|
+
import {
|
|
271
|
+
PERMIT2_ADDRESS,
|
|
272
|
+
buildPartialUserOperation,
|
|
273
|
+
erc20ApproveOp,
|
|
274
|
+
erc20TransferOp,
|
|
275
|
+
rawCallOp,
|
|
276
|
+
universalRouterAbi as universalRouterAbi2
|
|
277
|
+
} from "@pafi-dev/core";
|
|
278
|
+
function buildSwapUserOp(params) {
|
|
279
|
+
if (params.amountIn <= 0n) {
|
|
280
|
+
throw new Error("buildSwapUserOp: amountIn must be positive");
|
|
281
|
+
}
|
|
282
|
+
if (params.minAmountOut < 0n) {
|
|
283
|
+
throw new Error("buildSwapUserOp: minAmountOut must be non-negative");
|
|
284
|
+
}
|
|
285
|
+
if (params.gasFeeAmount < 0n) {
|
|
286
|
+
throw new Error("buildSwapUserOp: gasFeeAmount must be non-negative");
|
|
287
|
+
}
|
|
288
|
+
if (params.swapPath.length === 0) {
|
|
289
|
+
throw new Error(
|
|
290
|
+
"buildSwapUserOp: swapPath must contain at least one PathKey"
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
const { commands, inputs } = buildUniversalRouterExecuteArgs(
|
|
294
|
+
params.inputTokenAddress,
|
|
295
|
+
params.swapPath,
|
|
296
|
+
params.amountIn,
|
|
297
|
+
params.minAmountOut,
|
|
298
|
+
params.outputTokenAddress
|
|
299
|
+
);
|
|
300
|
+
const swapCallData = encodeFunctionData2({
|
|
301
|
+
abi: universalRouterAbi2,
|
|
302
|
+
functionName: "execute",
|
|
303
|
+
args: [commands, inputs, params.deadline]
|
|
304
|
+
});
|
|
305
|
+
const totalInputApproval = params.amountIn + params.gasFeeAmount;
|
|
306
|
+
const permit2ApproveData = buildPermit2ApprovalCalldata(
|
|
307
|
+
params.inputTokenAddress,
|
|
308
|
+
params.universalRouterAddress,
|
|
309
|
+
params.amountIn,
|
|
310
|
+
Number(params.deadline)
|
|
311
|
+
);
|
|
312
|
+
const operations = [
|
|
313
|
+
erc20ApproveOp(params.inputTokenAddress, PERMIT2_ADDRESS, totalInputApproval),
|
|
314
|
+
rawCallOp(PERMIT2_ADDRESS, permit2ApproveData),
|
|
315
|
+
rawCallOp(params.universalRouterAddress, swapCallData)
|
|
316
|
+
];
|
|
317
|
+
if (params.gasFeeAmount > 0n) {
|
|
318
|
+
operations.push(
|
|
319
|
+
erc20TransferOp(
|
|
320
|
+
params.inputTokenAddress,
|
|
321
|
+
params.feeRecipient,
|
|
322
|
+
params.gasFeeAmount
|
|
323
|
+
)
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
return buildPartialUserOperation({
|
|
327
|
+
sender: params.userAddress,
|
|
328
|
+
nonce: params.aaNonce,
|
|
329
|
+
operations,
|
|
330
|
+
gasLimits: {
|
|
331
|
+
callGasLimit: params.gasLimits?.callGasLimit ?? 700000n,
|
|
332
|
+
verificationGasLimit: params.gasLimits?.verificationGasLimit ?? 150000n,
|
|
333
|
+
preVerificationGas: params.gasLimits?.preVerificationGas ?? 50000n
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/api/handlers.ts
|
|
18
339
|
var TradingHandlers = class {
|
|
19
340
|
provider;
|
|
20
341
|
chainId;
|
|
@@ -38,29 +359,33 @@ var TradingHandlers = class {
|
|
|
38
359
|
throw new Error(`handleQuote: unsupported chainId ${request.chainId}`);
|
|
39
360
|
}
|
|
40
361
|
if (request.amount === 0n) {
|
|
41
|
-
return {
|
|
362
|
+
return {
|
|
363
|
+
inputAmount: 0n,
|
|
364
|
+
estimatedOutputAmount: 0n,
|
|
365
|
+
gasEstimate: 0n
|
|
366
|
+
};
|
|
42
367
|
}
|
|
43
|
-
const
|
|
44
|
-
const
|
|
368
|
+
const inputTokenAddress = getAddress(request.inputTokenAddress);
|
|
369
|
+
const outputTokenAddress = getAddress(request.outputTokenAddress);
|
|
45
370
|
const pools = request.pools ?? [];
|
|
46
371
|
try {
|
|
47
372
|
const best = await findBestQuote(
|
|
48
373
|
this.provider,
|
|
49
374
|
request.chainId,
|
|
50
|
-
|
|
51
|
-
|
|
375
|
+
inputTokenAddress,
|
|
376
|
+
outputTokenAddress,
|
|
52
377
|
request.amount,
|
|
53
378
|
pools
|
|
54
379
|
);
|
|
55
380
|
return {
|
|
56
|
-
|
|
57
|
-
|
|
381
|
+
inputAmount: request.amount,
|
|
382
|
+
estimatedOutputAmount: best.bestRoute.amountOut,
|
|
58
383
|
gasEstimate: best.bestRoute.gasEstimate
|
|
59
384
|
};
|
|
60
385
|
} catch {
|
|
61
386
|
return {
|
|
62
|
-
|
|
63
|
-
|
|
387
|
+
inputAmount: request.amount,
|
|
388
|
+
estimatedOutputAmount: 0n,
|
|
64
389
|
gasEstimate: 0n,
|
|
65
390
|
quoteError: "QUOTE_UNAVAILABLE"
|
|
66
391
|
};
|
|
@@ -85,71 +410,74 @@ var TradingHandlers = class {
|
|
|
85
410
|
if (request.amount <= 0n) {
|
|
86
411
|
throw new Error("handleSwap: amount must be positive");
|
|
87
412
|
}
|
|
88
|
-
const {
|
|
413
|
+
const { pafiFeeRecipient } = getContractAddresses(request.chainId);
|
|
89
414
|
const universalRouter = UNIVERSAL_ROUTER_ADDRESSES[request.chainId];
|
|
90
415
|
if (!universalRouter) {
|
|
91
416
|
throw new Error(`handleSwap: no UniversalRouter for chainId ${request.chainId}`);
|
|
92
417
|
}
|
|
93
|
-
const
|
|
418
|
+
const inputTokenAddress = getAddress(request.inputTokenAddress);
|
|
419
|
+
const outputTokenAddress = getAddress(request.outputTokenAddress);
|
|
94
420
|
const userAddress = getAddress(request.userAddress);
|
|
95
421
|
const pools = request.pools ?? [];
|
|
96
|
-
const
|
|
97
|
-
const gasFeePt = request.gasFeePt !== void 0 ? request.gasFeePt : await quoteOperatorFeePt({
|
|
422
|
+
const gasFeeAmount = request.gasFeeAmount !== void 0 ? request.gasFeeAmount : await quoteOperatorFeePt({
|
|
98
423
|
provider: this.provider,
|
|
99
424
|
chainId: request.chainId,
|
|
100
|
-
pointTokenAddress
|
|
101
|
-
});
|
|
425
|
+
pointTokenAddress: inputTokenAddress
|
|
426
|
+
}).catch(() => 0n);
|
|
102
427
|
let quoteResult;
|
|
103
428
|
try {
|
|
104
429
|
quoteResult = await findBestQuote(
|
|
105
430
|
this.provider,
|
|
106
431
|
request.chainId,
|
|
107
|
-
|
|
108
|
-
|
|
432
|
+
inputTokenAddress,
|
|
433
|
+
outputTokenAddress,
|
|
109
434
|
request.amount,
|
|
110
435
|
pools
|
|
111
436
|
);
|
|
112
437
|
} catch {
|
|
113
|
-
throw new Error(
|
|
438
|
+
throw new Error(
|
|
439
|
+
`handleSwap: no swap path found from ${inputTokenAddress} to ${outputTokenAddress}`
|
|
440
|
+
);
|
|
114
441
|
}
|
|
115
|
-
const
|
|
116
|
-
const
|
|
442
|
+
const hops = quoteResult.bestRoute.path.length;
|
|
443
|
+
const slippageBps = request.slippageBps ?? (hops > 1 ? 100 : 50);
|
|
444
|
+
const estimatedOutputAmount = quoteResult.bestRoute.amountOut;
|
|
445
|
+
const minAmountOut = estimatedOutputAmount * BigInt(1e4 - slippageBps) / 10000n;
|
|
117
446
|
const deadline = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
118
|
-
const userOp =
|
|
447
|
+
const userOp = buildSwapUserOp({
|
|
119
448
|
userAddress,
|
|
120
449
|
aaNonce: request.aaNonce,
|
|
121
|
-
|
|
122
|
-
outputTokenAddress
|
|
450
|
+
inputTokenAddress,
|
|
451
|
+
outputTokenAddress,
|
|
123
452
|
universalRouterAddress: universalRouter,
|
|
124
453
|
amountIn: request.amount,
|
|
125
454
|
minAmountOut,
|
|
126
455
|
swapPath: quoteResult.bestRoute.path,
|
|
127
456
|
deadline,
|
|
128
|
-
|
|
129
|
-
// Recipient is always PAFI's canonical address — sponsor-relayer's
|
|
130
|
-
// L1 gate will reject any other recipient anyway. No override.
|
|
457
|
+
gasFeeAmount,
|
|
131
458
|
feeRecipient: pafiFeeRecipient
|
|
132
459
|
});
|
|
133
|
-
const userOpFallback =
|
|
460
|
+
const userOpFallback = gasFeeAmount > 0n ? buildSwapUserOp({
|
|
134
461
|
userAddress,
|
|
135
462
|
aaNonce: request.aaNonce,
|
|
136
|
-
|
|
137
|
-
outputTokenAddress
|
|
463
|
+
inputTokenAddress,
|
|
464
|
+
outputTokenAddress,
|
|
138
465
|
universalRouterAddress: universalRouter,
|
|
139
466
|
amountIn: request.amount,
|
|
140
467
|
minAmountOut,
|
|
141
468
|
swapPath: quoteResult.bestRoute.path,
|
|
142
469
|
deadline,
|
|
143
|
-
|
|
144
|
-
feeRecipient:
|
|
470
|
+
gasFeeAmount: 0n,
|
|
471
|
+
feeRecipient: pafiFeeRecipient
|
|
145
472
|
}) : void 0;
|
|
146
473
|
return {
|
|
147
474
|
userOp,
|
|
148
475
|
userOpFallback,
|
|
149
|
-
|
|
476
|
+
estimatedOutputAmount,
|
|
150
477
|
minAmountOut,
|
|
478
|
+
hops,
|
|
151
479
|
deadline,
|
|
152
|
-
feeAmountUsed:
|
|
480
|
+
feeAmountUsed: gasFeeAmount,
|
|
153
481
|
feeRecipient: pafiFeeRecipient
|
|
154
482
|
};
|
|
155
483
|
}
|
|
@@ -330,6 +658,20 @@ import { fetchPafiPools, PAFI_SUBGRAPH_URL } from "@pafi-dev/core";
|
|
|
330
658
|
export {
|
|
331
659
|
PAFI_SUBGRAPH_URL,
|
|
332
660
|
TradingHandlers,
|
|
333
|
-
|
|
661
|
+
buildAllPaths,
|
|
662
|
+
buildErc20ApprovalCalldata,
|
|
663
|
+
buildPermit2ApprovalCalldata,
|
|
664
|
+
buildSwapFromQuote,
|
|
665
|
+
buildSwapUserOp,
|
|
666
|
+
buildUniversalRouterExecuteArgs,
|
|
667
|
+
buildV4SwapInput,
|
|
668
|
+
checkAllowance,
|
|
669
|
+
combineRoutes,
|
|
670
|
+
fetchPafiPools,
|
|
671
|
+
findBestQuote,
|
|
672
|
+
quoteBestRoute,
|
|
673
|
+
quoteExactInput,
|
|
674
|
+
quoteExactInputSingle,
|
|
675
|
+
simulateSwap
|
|
334
676
|
};
|
|
335
677
|
//# sourceMappingURL=index.js.map
|