damm-sdk 1.4.37 → 1.4.39

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.
@@ -0,0 +1,977 @@
1
+ /**
2
+ * Pure Pendle Router V4 calldata encoders.
3
+ *
4
+ * All functions are pure: given explicit params, they return deterministic calldata
5
+ * via viem's `encodeFunctionData`. No network calls, no Pendle API dependency.
6
+ *
7
+ * Clean-shape guarantee (ADR-0001):
8
+ * - `TokenInput.pendleSwap` is always forced to address(0).
9
+ * - `TokenInput.swapData` is always `(NONE=0, address(0), 0x, false)`.
10
+ * - `TokenOutput.pendleSwap` / `swapData` are forced the same way.
11
+ * - `LimitOrderData` is always `(address(0), 0, [], [], 0x)`.
12
+ *
13
+ * Callers provide the user-facing subset:
14
+ * - `TokenInputParams` = `{ tokenIn, netTokenIn, tokenMintSy }`
15
+ * - `TokenOutputParams` = `{ tokenOut, minTokenOut, tokenRedeemSy }`
16
+ * - `ApproxParams` = all five fields (obtained from the Pendle Hosted API)
17
+ *
18
+ * The encoder constructs the full on-chain structs internally — the caller cannot
19
+ * supply a non-clean `pendleSwap` or `limitRouter`.
20
+ *
21
+ * This module also contains the refactored claim encoders
22
+ * (`redeemDueInterestAndRewards` V1 + merkle `claim`), migrated from ethers v5
23
+ * to viem while keeping identical external behaviour and exports.
24
+ *
25
+ * Selectors verified against pendle-core-v2-public source + Monad/mainnet deployments
26
+ * (2026-06-29). PT↔YT swap functions (`swapExactPtForYt` / `swapExactYtForPt`) are
27
+ * intentionally absent — they do not exist on the Router V4.
28
+ */
29
+
30
+ import { encodeFunctionData, type Address } from "viem";
31
+ import { type Call, type HexString, type Unwrapable, createCall } from "../../types/index.ts";
32
+ import pendleRouterAbi from "./pendle.router.abi.ts";
33
+ import pendleMerkleDistributorAbi from "./pendle.merkle-distributor.abi.ts";
34
+
35
+ // =============================================================================
36
+ // Exported parameter types (what callers provide)
37
+ // =============================================================================
38
+
39
+ /**
40
+ * On-chain binary-search hint. All five fields are required because they carry
41
+ * market-state information computed by the Pendle Hosted API per request.
42
+ */
43
+ export type ApproxParams = Readonly<{
44
+ guessMin: bigint;
45
+ guessMax: bigint;
46
+ guessOffchain: bigint;
47
+ maxIteration: bigint;
48
+ eps: bigint;
49
+ }>;
50
+
51
+ /**
52
+ * User-facing TokenInput subset. The encoder forces `pendleSwap=0x0` and
53
+ * `swapData=CLEAN_SWAP_DATA` — the caller cannot provide a non-clean shape.
54
+ * Requires `tokenIn == tokenMintSy` for the aggregator-free code path.
55
+ */
56
+ export type TokenInputParams = Readonly<{
57
+ tokenIn: Address;
58
+ netTokenIn: bigint;
59
+ tokenMintSy: Address;
60
+ }>;
61
+
62
+ /**
63
+ * User-facing TokenOutput subset. The encoder forces `pendleSwap=0x0` and
64
+ * `swapData=CLEAN_SWAP_DATA`.
65
+ * Requires `tokenOut == tokenRedeemSy` for the aggregator-free code path.
66
+ */
67
+ export type TokenOutputParams = Readonly<{
68
+ tokenOut: Address;
69
+ minTokenOut: bigint;
70
+ tokenRedeemSy: Address;
71
+ }>;
72
+
73
+ // =============================================================================
74
+ // Internal clean-shape constants (not exported — callers cannot override)
75
+ // =============================================================================
76
+
77
+ const ZERO_ADDRESS: Address = "0x0000000000000000000000000000000000000000";
78
+
79
+ /** SwapData with aggregator disabled. swapType=NONE(0), all addresses/data zeroed. */
80
+ const CLEAN_SWAP_DATA = {
81
+ swapType: 0,
82
+ extRouter: ZERO_ADDRESS,
83
+ extCalldata: "0x" as HexString,
84
+ needScale: false,
85
+ } as const;
86
+
87
+ /**
88
+ * Fully empty LimitOrderData — limitRouter=0x0, no fills, no optData.
89
+ * Arrays typed as `never[]` so they are assignable to any concrete FillOrderParams[].
90
+ */
91
+ const EMPTY_LIMIT_ORDER_DATA = {
92
+ limitRouter: ZERO_ADDRESS,
93
+ epsSkipMarket: 0n,
94
+ normalFills: [] as never[],
95
+ flashFills: [] as never[],
96
+ optData: "0x" as HexString,
97
+ };
98
+
99
+ /** Expand caller-supplied TokenInputParams into the full on-chain TokenInput struct. */
100
+ const makeCleanTokenInput = ({ tokenIn, netTokenIn, tokenMintSy }: TokenInputParams) =>
101
+ ({
102
+ tokenIn,
103
+ netTokenIn,
104
+ tokenMintSy,
105
+ pendleSwap: ZERO_ADDRESS,
106
+ swapData: CLEAN_SWAP_DATA,
107
+ }) as const;
108
+
109
+ /** Expand caller-supplied TokenOutputParams into the full on-chain TokenOutput struct. */
110
+ const makeCleanTokenOutput = ({ tokenOut, minTokenOut, tokenRedeemSy }: TokenOutputParams) =>
111
+ ({
112
+ tokenOut,
113
+ minTokenOut,
114
+ tokenRedeemSy,
115
+ pendleSwap: ZERO_ADDRESS,
116
+ swapData: CLEAN_SWAP_DATA,
117
+ }) as const;
118
+
119
+ // =============================================================================
120
+ // Shared Trx builder helper
121
+ // =============================================================================
122
+
123
+ const routerTrx = (routerAddress: Address, data: HexString): Unwrapable<Call> =>
124
+ createCall({ to: routerAddress, data, operation: 0, value: 0n });
125
+
126
+ const distributorTrx = (distributorAddress: Address, data: HexString): Unwrapable<Call> =>
127
+ createCall({ to: distributorAddress, data, operation: 0, value: 0n });
128
+
129
+ // =============================================================================
130
+ // ActionMiscV3 — redeemDueInterestAndRewards (V1) — on-chain claim
131
+ // Refactored from ethers v5 → viem (behaviour unchanged).
132
+ // =============================================================================
133
+
134
+ export type PendleRedeemRewardsArgs = Readonly<{
135
+ user: Address;
136
+ sys: Address[];
137
+ yts: Address[];
138
+ markets: Address[];
139
+ }>;
140
+
141
+ export const pendleRedeemRewardsCalldata = ({ user, sys, yts, markets }: PendleRedeemRewardsArgs): HexString =>
142
+ encodeFunctionData({
143
+ abi: pendleRouterAbi,
144
+ functionName: "redeemDueInterestAndRewards",
145
+ args: [user, sys, yts, markets],
146
+ });
147
+
148
+ export const pendleRedeemRewardsTrx = ({
149
+ args,
150
+ routerAddress,
151
+ }: {
152
+ args: PendleRedeemRewardsArgs;
153
+ routerAddress: Address;
154
+ }): Unwrapable<Call> => routerTrx(routerAddress, pendleRedeemRewardsCalldata(args));
155
+
156
+ // =============================================================================
157
+ // MerkleDistributor — claim (off-chain merkle rewards)
158
+ // Refactored from ethers v5 → viem (behaviour unchanged).
159
+ // =============================================================================
160
+
161
+ export type PendleMerkleClaimArgs = Readonly<{
162
+ receiver: Address;
163
+ tokens: Address[];
164
+ totalAccrueds: bigint[];
165
+ proofs: HexString[][];
166
+ }>;
167
+
168
+ export const pendleMerkleClaimCalldata = ({
169
+ receiver,
170
+ tokens,
171
+ totalAccrueds,
172
+ proofs,
173
+ }: PendleMerkleClaimArgs): HexString =>
174
+ encodeFunctionData({
175
+ abi: pendleMerkleDistributorAbi,
176
+ functionName: "claim",
177
+ args: [receiver, tokens, totalAccrueds, proofs],
178
+ });
179
+
180
+ export const pendleMerkleClaimTrx = ({
181
+ args,
182
+ distributorAddress,
183
+ }: {
184
+ args: PendleMerkleClaimArgs;
185
+ distributorAddress: Address;
186
+ }): Unwrapable<Call> => distributorTrx(distributorAddress, pendleMerkleClaimCalldata(args));
187
+
188
+ // =============================================================================
189
+ // ActionMiscV3 — SY wrap/unwrap
190
+ // =============================================================================
191
+
192
+ // ---- mintSyFromToken -------------------------------------------------------
193
+ // Wraps a SY-native token into SY. Clean shape: pendleSwap=0, swapType=NONE.
194
+
195
+ export type MintSyFromTokenArgs = Readonly<{
196
+ receiver: Address;
197
+ sy: Address;
198
+ minSyOut: bigint;
199
+ input: TokenInputParams;
200
+ }>;
201
+
202
+ export const mintSyFromTokenCalldata = ({ receiver, sy, minSyOut, input }: MintSyFromTokenArgs): HexString =>
203
+ encodeFunctionData({
204
+ abi: pendleRouterAbi,
205
+ functionName: "mintSyFromToken",
206
+ args: [receiver, sy, minSyOut, makeCleanTokenInput(input)],
207
+ });
208
+
209
+ export const mintSyFromTokenTrx = ({
210
+ args,
211
+ routerAddress,
212
+ }: {
213
+ args: MintSyFromTokenArgs;
214
+ routerAddress: Address;
215
+ }): Unwrapable<Call> => routerTrx(routerAddress, mintSyFromTokenCalldata(args));
216
+
217
+ // ---- redeemSyToToken -------------------------------------------------------
218
+ // Unwraps SY back to a token. Clean shape: pendleSwap=0, swapType=NONE.
219
+
220
+ export type RedeemSyToTokenArgs = Readonly<{
221
+ receiver: Address;
222
+ sy: Address;
223
+ netSyIn: bigint;
224
+ output: TokenOutputParams;
225
+ }>;
226
+
227
+ export const redeemSyToTokenCalldata = ({ receiver, sy, netSyIn, output }: RedeemSyToTokenArgs): HexString =>
228
+ encodeFunctionData({
229
+ abi: pendleRouterAbi,
230
+ functionName: "redeemSyToToken",
231
+ args: [receiver, sy, netSyIn, makeCleanTokenOutput(output)],
232
+ });
233
+
234
+ export const redeemSyToTokenTrx = ({
235
+ args,
236
+ routerAddress,
237
+ }: {
238
+ args: RedeemSyToTokenArgs;
239
+ routerAddress: Address;
240
+ }): Unwrapable<Call> => routerTrx(routerAddress, redeemSyToTokenCalldata(args));
241
+
242
+ // =============================================================================
243
+ // ActionMiscV3 — Mint/Redeem PY (PT + YT)
244
+ // =============================================================================
245
+
246
+ // ---- mintPyFromToken -------------------------------------------------------
247
+
248
+ export type MintPyFromTokenArgs = Readonly<{
249
+ receiver: Address;
250
+ yt: Address;
251
+ minPyOut: bigint;
252
+ input: TokenInputParams;
253
+ }>;
254
+
255
+ export const mintPyFromTokenCalldata = ({ receiver, yt, minPyOut, input }: MintPyFromTokenArgs): HexString =>
256
+ encodeFunctionData({
257
+ abi: pendleRouterAbi,
258
+ functionName: "mintPyFromToken",
259
+ args: [receiver, yt, minPyOut, makeCleanTokenInput(input)],
260
+ });
261
+
262
+ export const mintPyFromTokenTrx = ({
263
+ args,
264
+ routerAddress,
265
+ }: {
266
+ args: MintPyFromTokenArgs;
267
+ routerAddress: Address;
268
+ }): Unwrapable<Call> => routerTrx(routerAddress, mintPyFromTokenCalldata(args));
269
+
270
+ // ---- redeemPyToToken -------------------------------------------------------
271
+
272
+ export type RedeemPyToTokenArgs = Readonly<{
273
+ receiver: Address;
274
+ yt: Address;
275
+ netPyIn: bigint;
276
+ output: TokenOutputParams;
277
+ }>;
278
+
279
+ export const redeemPyToTokenCalldata = ({ receiver, yt, netPyIn, output }: RedeemPyToTokenArgs): HexString =>
280
+ encodeFunctionData({
281
+ abi: pendleRouterAbi,
282
+ functionName: "redeemPyToToken",
283
+ args: [receiver, yt, netPyIn, makeCleanTokenOutput(output)],
284
+ });
285
+
286
+ export const redeemPyToTokenTrx = ({
287
+ args,
288
+ routerAddress,
289
+ }: {
290
+ args: RedeemPyToTokenArgs;
291
+ routerAddress: Address;
292
+ }): Unwrapable<Call> => routerTrx(routerAddress, redeemPyToTokenCalldata(args));
293
+
294
+ // ---- mintPyFromSy ----------------------------------------------------------
295
+ // No aggregator struct at all — the simplest mint path.
296
+
297
+ export type MintPyFromSyArgs = Readonly<{
298
+ receiver: Address;
299
+ yt: Address;
300
+ netSyIn: bigint;
301
+ minPyOut: bigint;
302
+ }>;
303
+
304
+ export const mintPyFromSyCalldata = ({ receiver, yt, netSyIn, minPyOut }: MintPyFromSyArgs): HexString =>
305
+ encodeFunctionData({
306
+ abi: pendleRouterAbi,
307
+ functionName: "mintPyFromSy",
308
+ args: [receiver, yt, netSyIn, minPyOut],
309
+ });
310
+
311
+ export const mintPyFromSyTrx = ({
312
+ args,
313
+ routerAddress,
314
+ }: {
315
+ args: MintPyFromSyArgs;
316
+ routerAddress: Address;
317
+ }): Unwrapable<Call> => routerTrx(routerAddress, mintPyFromSyCalldata(args));
318
+
319
+ // ---- redeemPyToSy ----------------------------------------------------------
320
+ // No aggregator struct at all.
321
+
322
+ export type RedeemPyToSyArgs = Readonly<{
323
+ receiver: Address;
324
+ yt: Address;
325
+ netPyIn: bigint;
326
+ minSyOut: bigint;
327
+ }>;
328
+
329
+ export const redeemPyToSyCalldata = ({ receiver, yt, netPyIn, minSyOut }: RedeemPyToSyArgs): HexString =>
330
+ encodeFunctionData({
331
+ abi: pendleRouterAbi,
332
+ functionName: "redeemPyToSy",
333
+ args: [receiver, yt, netPyIn, minSyOut],
334
+ });
335
+
336
+ export const redeemPyToSyTrx = ({
337
+ args,
338
+ routerAddress,
339
+ }: {
340
+ args: RedeemPyToSyArgs;
341
+ routerAddress: Address;
342
+ }): Unwrapable<Call> => routerTrx(routerAddress, redeemPyToSyCalldata(args));
343
+
344
+ // =============================================================================
345
+ // ActionSwapPTV3 — PT swaps
346
+ // =============================================================================
347
+
348
+ // ---- swapExactTokenForPt ---------------------------------------------------
349
+ // Token → PT via SY. Input + limit forced clean.
350
+
351
+ export type SwapExactTokenForPtArgs = Readonly<{
352
+ receiver: Address;
353
+ market: Address;
354
+ minPtOut: bigint;
355
+ guess: ApproxParams;
356
+ input: TokenInputParams;
357
+ }>;
358
+
359
+ export const swapExactTokenForPtCalldata = ({
360
+ receiver,
361
+ market,
362
+ minPtOut,
363
+ guess,
364
+ input,
365
+ }: SwapExactTokenForPtArgs): HexString =>
366
+ encodeFunctionData({
367
+ abi: pendleRouterAbi,
368
+ functionName: "swapExactTokenForPt",
369
+ args: [receiver, market, minPtOut, guess, makeCleanTokenInput(input), EMPTY_LIMIT_ORDER_DATA],
370
+ });
371
+
372
+ export const swapExactTokenForPtTrx = ({
373
+ args,
374
+ routerAddress,
375
+ }: {
376
+ args: SwapExactTokenForPtArgs;
377
+ routerAddress: Address;
378
+ }): Unwrapable<Call> => routerTrx(routerAddress, swapExactTokenForPtCalldata(args));
379
+
380
+ // ---- swapExactSyForPt ------------------------------------------------------
381
+ // SY → PT. No aggregator struct; limit forced clean.
382
+
383
+ export type SwapExactSyForPtArgs = Readonly<{
384
+ receiver: Address;
385
+ market: Address;
386
+ exactSyIn: bigint;
387
+ minPtOut: bigint;
388
+ guess: ApproxParams;
389
+ }>;
390
+
391
+ export const swapExactSyForPtCalldata = ({
392
+ receiver,
393
+ market,
394
+ exactSyIn,
395
+ minPtOut,
396
+ guess,
397
+ }: SwapExactSyForPtArgs): HexString =>
398
+ encodeFunctionData({
399
+ abi: pendleRouterAbi,
400
+ functionName: "swapExactSyForPt",
401
+ args: [receiver, market, exactSyIn, minPtOut, guess, EMPTY_LIMIT_ORDER_DATA],
402
+ });
403
+
404
+ export const swapExactSyForPtTrx = ({
405
+ args,
406
+ routerAddress,
407
+ }: {
408
+ args: SwapExactSyForPtArgs;
409
+ routerAddress: Address;
410
+ }): Unwrapable<Call> => routerTrx(routerAddress, swapExactSyForPtCalldata(args));
411
+
412
+ // ---- swapExactPtForToken ---------------------------------------------------
413
+ // PT → token via SY. Output + limit forced clean.
414
+
415
+ export type SwapExactPtForTokenArgs = Readonly<{
416
+ receiver: Address;
417
+ market: Address;
418
+ exactPtIn: bigint;
419
+ output: TokenOutputParams;
420
+ }>;
421
+
422
+ export const swapExactPtForTokenCalldata = ({
423
+ receiver,
424
+ market,
425
+ exactPtIn,
426
+ output,
427
+ }: SwapExactPtForTokenArgs): HexString =>
428
+ encodeFunctionData({
429
+ abi: pendleRouterAbi,
430
+ functionName: "swapExactPtForToken",
431
+ args: [receiver, market, exactPtIn, makeCleanTokenOutput(output), EMPTY_LIMIT_ORDER_DATA],
432
+ });
433
+
434
+ export const swapExactPtForTokenTrx = ({
435
+ args,
436
+ routerAddress,
437
+ }: {
438
+ args: SwapExactPtForTokenArgs;
439
+ routerAddress: Address;
440
+ }): Unwrapable<Call> => routerTrx(routerAddress, swapExactPtForTokenCalldata(args));
441
+
442
+ // ---- swapExactPtForSy ------------------------------------------------------
443
+ // PT → SY. No aggregator struct; limit forced clean.
444
+
445
+ export type SwapExactPtForSyArgs = Readonly<{
446
+ receiver: Address;
447
+ market: Address;
448
+ exactPtIn: bigint;
449
+ minSyOut: bigint;
450
+ }>;
451
+
452
+ export const swapExactPtForSyCalldata = ({ receiver, market, exactPtIn, minSyOut }: SwapExactPtForSyArgs): HexString =>
453
+ encodeFunctionData({
454
+ abi: pendleRouterAbi,
455
+ functionName: "swapExactPtForSy",
456
+ args: [receiver, market, exactPtIn, minSyOut, EMPTY_LIMIT_ORDER_DATA],
457
+ });
458
+
459
+ export const swapExactPtForSyTrx = ({
460
+ args,
461
+ routerAddress,
462
+ }: {
463
+ args: SwapExactPtForSyArgs;
464
+ routerAddress: Address;
465
+ }): Unwrapable<Call> => routerTrx(routerAddress, swapExactPtForSyCalldata(args));
466
+
467
+ // =============================================================================
468
+ // ActionSwapYTV3 — YT swaps
469
+ // =============================================================================
470
+
471
+ // ---- swapExactTokenForYt ---------------------------------------------------
472
+ // Token → YT via SY. Input + limit forced clean.
473
+
474
+ export type SwapExactTokenForYtArgs = Readonly<{
475
+ receiver: Address;
476
+ market: Address;
477
+ minYtOut: bigint;
478
+ guess: ApproxParams;
479
+ input: TokenInputParams;
480
+ }>;
481
+
482
+ export const swapExactTokenForYtCalldata = ({
483
+ receiver,
484
+ market,
485
+ minYtOut,
486
+ guess,
487
+ input,
488
+ }: SwapExactTokenForYtArgs): HexString =>
489
+ encodeFunctionData({
490
+ abi: pendleRouterAbi,
491
+ functionName: "swapExactTokenForYt",
492
+ args: [receiver, market, minYtOut, guess, makeCleanTokenInput(input), EMPTY_LIMIT_ORDER_DATA],
493
+ });
494
+
495
+ export const swapExactTokenForYtTrx = ({
496
+ args,
497
+ routerAddress,
498
+ }: {
499
+ args: SwapExactTokenForYtArgs;
500
+ routerAddress: Address;
501
+ }): Unwrapable<Call> => routerTrx(routerAddress, swapExactTokenForYtCalldata(args));
502
+
503
+ // ---- swapExactSyForYt ------------------------------------------------------
504
+ // SY → YT. No aggregator struct; limit forced clean.
505
+
506
+ export type SwapExactSyForYtArgs = Readonly<{
507
+ receiver: Address;
508
+ market: Address;
509
+ exactSyIn: bigint;
510
+ minYtOut: bigint;
511
+ guess: ApproxParams;
512
+ }>;
513
+
514
+ export const swapExactSyForYtCalldata = ({
515
+ receiver,
516
+ market,
517
+ exactSyIn,
518
+ minYtOut,
519
+ guess,
520
+ }: SwapExactSyForYtArgs): HexString =>
521
+ encodeFunctionData({
522
+ abi: pendleRouterAbi,
523
+ functionName: "swapExactSyForYt",
524
+ args: [receiver, market, exactSyIn, minYtOut, guess, EMPTY_LIMIT_ORDER_DATA],
525
+ });
526
+
527
+ export const swapExactSyForYtTrx = ({
528
+ args,
529
+ routerAddress,
530
+ }: {
531
+ args: SwapExactSyForYtArgs;
532
+ routerAddress: Address;
533
+ }): Unwrapable<Call> => routerTrx(routerAddress, swapExactSyForYtCalldata(args));
534
+
535
+ // ---- swapExactYtForToken ---------------------------------------------------
536
+ // YT → token via SY. Output + limit forced clean.
537
+
538
+ export type SwapExactYtForTokenArgs = Readonly<{
539
+ receiver: Address;
540
+ market: Address;
541
+ exactYtIn: bigint;
542
+ output: TokenOutputParams;
543
+ }>;
544
+
545
+ export const swapExactYtForTokenCalldata = ({
546
+ receiver,
547
+ market,
548
+ exactYtIn,
549
+ output,
550
+ }: SwapExactYtForTokenArgs): HexString =>
551
+ encodeFunctionData({
552
+ abi: pendleRouterAbi,
553
+ functionName: "swapExactYtForToken",
554
+ args: [receiver, market, exactYtIn, makeCleanTokenOutput(output), EMPTY_LIMIT_ORDER_DATA],
555
+ });
556
+
557
+ export const swapExactYtForTokenTrx = ({
558
+ args,
559
+ routerAddress,
560
+ }: {
561
+ args: SwapExactYtForTokenArgs;
562
+ routerAddress: Address;
563
+ }): Unwrapable<Call> => routerTrx(routerAddress, swapExactYtForTokenCalldata(args));
564
+
565
+ // ---- swapExactYtForSy ------------------------------------------------------
566
+ // YT → SY. No aggregator struct; limit forced clean.
567
+
568
+ export type SwapExactYtForSyArgs = Readonly<{
569
+ receiver: Address;
570
+ market: Address;
571
+ exactYtIn: bigint;
572
+ minSyOut: bigint;
573
+ }>;
574
+
575
+ export const swapExactYtForSyCalldata = ({ receiver, market, exactYtIn, minSyOut }: SwapExactYtForSyArgs): HexString =>
576
+ encodeFunctionData({
577
+ abi: pendleRouterAbi,
578
+ functionName: "swapExactYtForSy",
579
+ args: [receiver, market, exactYtIn, minSyOut, EMPTY_LIMIT_ORDER_DATA],
580
+ });
581
+
582
+ export const swapExactYtForSyTrx = ({
583
+ args,
584
+ routerAddress,
585
+ }: {
586
+ args: SwapExactYtForSyArgs;
587
+ routerAddress: Address;
588
+ }): Unwrapable<Call> => routerTrx(routerAddress, swapExactYtForSyCalldata(args));
589
+
590
+ // =============================================================================
591
+ // ActionAddRemoveLiqV3 — add liquidity
592
+ // =============================================================================
593
+
594
+ // ---- addLiquiditySingleToken -----------------------------------------------
595
+ // Token → LP (has price impact). Input + limit forced clean.
596
+
597
+ export type AddLiquiditySingleTokenArgs = Readonly<{
598
+ receiver: Address;
599
+ market: Address;
600
+ minLpOut: bigint;
601
+ guess: ApproxParams;
602
+ input: TokenInputParams;
603
+ }>;
604
+
605
+ export const addLiquiditySingleTokenCalldata = ({
606
+ receiver,
607
+ market,
608
+ minLpOut,
609
+ guess,
610
+ input,
611
+ }: AddLiquiditySingleTokenArgs): HexString =>
612
+ encodeFunctionData({
613
+ abi: pendleRouterAbi,
614
+ functionName: "addLiquiditySingleToken",
615
+ args: [receiver, market, minLpOut, guess, makeCleanTokenInput(input), EMPTY_LIMIT_ORDER_DATA],
616
+ });
617
+
618
+ export const addLiquiditySingleTokenTrx = ({
619
+ args,
620
+ routerAddress,
621
+ }: {
622
+ args: AddLiquiditySingleTokenArgs;
623
+ routerAddress: Address;
624
+ }): Unwrapable<Call> => routerTrx(routerAddress, addLiquiditySingleTokenCalldata(args));
625
+
626
+ // ---- addLiquiditySingleSy --------------------------------------------------
627
+ // SY → LP (has price impact). No aggregator struct; limit forced clean.
628
+
629
+ export type AddLiquiditySingleSyArgs = Readonly<{
630
+ receiver: Address;
631
+ market: Address;
632
+ netSyIn: bigint;
633
+ minLpOut: bigint;
634
+ guess: ApproxParams;
635
+ }>;
636
+
637
+ export const addLiquiditySingleSyCalldata = ({
638
+ receiver,
639
+ market,
640
+ netSyIn,
641
+ minLpOut,
642
+ guess,
643
+ }: AddLiquiditySingleSyArgs): HexString =>
644
+ encodeFunctionData({
645
+ abi: pendleRouterAbi,
646
+ functionName: "addLiquiditySingleSy",
647
+ args: [receiver, market, netSyIn, minLpOut, guess, EMPTY_LIMIT_ORDER_DATA],
648
+ });
649
+
650
+ export const addLiquiditySingleSyTrx = ({
651
+ args,
652
+ routerAddress,
653
+ }: {
654
+ args: AddLiquiditySingleSyArgs;
655
+ routerAddress: Address;
656
+ }): Unwrapable<Call> => routerTrx(routerAddress, addLiquiditySingleSyCalldata(args));
657
+
658
+ // ---- addLiquiditySinglePt --------------------------------------------------
659
+ // PT → LP. No aggregator struct; limit forced clean.
660
+
661
+ export type AddLiquiditySinglePtArgs = Readonly<{
662
+ receiver: Address;
663
+ market: Address;
664
+ netPtIn: bigint;
665
+ minLpOut: bigint;
666
+ guess: ApproxParams;
667
+ }>;
668
+
669
+ export const addLiquiditySinglePtCalldata = ({
670
+ receiver,
671
+ market,
672
+ netPtIn,
673
+ minLpOut,
674
+ guess,
675
+ }: AddLiquiditySinglePtArgs): HexString =>
676
+ encodeFunctionData({
677
+ abi: pendleRouterAbi,
678
+ functionName: "addLiquiditySinglePt",
679
+ args: [receiver, market, netPtIn, minLpOut, guess, EMPTY_LIMIT_ORDER_DATA],
680
+ });
681
+
682
+ export const addLiquiditySinglePtTrx = ({
683
+ args,
684
+ routerAddress,
685
+ }: {
686
+ args: AddLiquiditySinglePtArgs;
687
+ routerAddress: Address;
688
+ }): Unwrapable<Call> => routerTrx(routerAddress, addLiquiditySinglePtCalldata(args));
689
+
690
+ // ---- addLiquiditySingleTokenKeepYt (ZPI) -----------------------------------
691
+ // Token → LP + YT (Zero Price Impact). Input forced clean. No LimitOrderData param.
692
+
693
+ export type AddLiquiditySingleTokenKeepYtArgs = Readonly<{
694
+ receiver: Address;
695
+ market: Address;
696
+ minLpOut: bigint;
697
+ minYtOut: bigint;
698
+ input: TokenInputParams;
699
+ }>;
700
+
701
+ export const addLiquiditySingleTokenKeepYtCalldata = ({
702
+ receiver,
703
+ market,
704
+ minLpOut,
705
+ minYtOut,
706
+ input,
707
+ }: AddLiquiditySingleTokenKeepYtArgs): HexString =>
708
+ encodeFunctionData({
709
+ abi: pendleRouterAbi,
710
+ functionName: "addLiquiditySingleTokenKeepYt",
711
+ args: [receiver, market, minLpOut, minYtOut, makeCleanTokenInput(input)],
712
+ });
713
+
714
+ export const addLiquiditySingleTokenKeepYtTrx = ({
715
+ args,
716
+ routerAddress,
717
+ }: {
718
+ args: AddLiquiditySingleTokenKeepYtArgs;
719
+ routerAddress: Address;
720
+ }): Unwrapable<Call> => routerTrx(routerAddress, addLiquiditySingleTokenKeepYtCalldata(args));
721
+
722
+ // ---- addLiquiditySingleSyKeepYt (ZPI) -------------------------------------
723
+ // SY → LP + YT (Zero Price Impact). No aggregator struct, no LimitOrderData.
724
+ // The cleanest ZPI path — Hosted API outputs=[market, YT] triggers this function.
725
+
726
+ export type AddLiquiditySingleSyKeepYtArgs = Readonly<{
727
+ receiver: Address;
728
+ market: Address;
729
+ netSyIn: bigint;
730
+ minLpOut: bigint;
731
+ minYtOut: bigint;
732
+ }>;
733
+
734
+ export const addLiquiditySingleSyKeepYtCalldata = ({
735
+ receiver,
736
+ market,
737
+ netSyIn,
738
+ minLpOut,
739
+ minYtOut,
740
+ }: AddLiquiditySingleSyKeepYtArgs): HexString =>
741
+ encodeFunctionData({
742
+ abi: pendleRouterAbi,
743
+ functionName: "addLiquiditySingleSyKeepYt",
744
+ args: [receiver, market, netSyIn, minLpOut, minYtOut],
745
+ });
746
+
747
+ export const addLiquiditySingleSyKeepYtTrx = ({
748
+ args,
749
+ routerAddress,
750
+ }: {
751
+ args: AddLiquiditySingleSyKeepYtArgs;
752
+ routerAddress: Address;
753
+ }): Unwrapable<Call> => routerTrx(routerAddress, addLiquiditySingleSyKeepYtCalldata(args));
754
+
755
+ // ---- addLiquidityDualTokenAndPt --------------------------------------------
756
+ // Token + PT → LP. Input forced clean. No LimitOrderData param.
757
+
758
+ export type AddLiquidityDualTokenAndPtArgs = Readonly<{
759
+ receiver: Address;
760
+ market: Address;
761
+ input: TokenInputParams;
762
+ netPtDesired: bigint;
763
+ minLpOut: bigint;
764
+ }>;
765
+
766
+ export const addLiquidityDualTokenAndPtCalldata = ({
767
+ receiver,
768
+ market,
769
+ input,
770
+ netPtDesired,
771
+ minLpOut,
772
+ }: AddLiquidityDualTokenAndPtArgs): HexString =>
773
+ encodeFunctionData({
774
+ abi: pendleRouterAbi,
775
+ functionName: "addLiquidityDualTokenAndPt",
776
+ args: [receiver, market, makeCleanTokenInput(input), netPtDesired, minLpOut],
777
+ });
778
+
779
+ export const addLiquidityDualTokenAndPtTrx = ({
780
+ args,
781
+ routerAddress,
782
+ }: {
783
+ args: AddLiquidityDualTokenAndPtArgs;
784
+ routerAddress: Address;
785
+ }): Unwrapable<Call> => routerTrx(routerAddress, addLiquidityDualTokenAndPtCalldata(args));
786
+
787
+ // ---- addLiquidityDualSyAndPt -----------------------------------------------
788
+ // SY + PT → LP. No aggregator struct at all — the simplest dual add path.
789
+
790
+ export type AddLiquidityDualSyAndPtArgs = Readonly<{
791
+ receiver: Address;
792
+ market: Address;
793
+ netSyDesired: bigint;
794
+ netPtDesired: bigint;
795
+ minLpOut: bigint;
796
+ }>;
797
+
798
+ export const addLiquidityDualSyAndPtCalldata = ({
799
+ receiver,
800
+ market,
801
+ netSyDesired,
802
+ netPtDesired,
803
+ minLpOut,
804
+ }: AddLiquidityDualSyAndPtArgs): HexString =>
805
+ encodeFunctionData({
806
+ abi: pendleRouterAbi,
807
+ functionName: "addLiquidityDualSyAndPt",
808
+ args: [receiver, market, netSyDesired, netPtDesired, minLpOut],
809
+ });
810
+
811
+ export const addLiquidityDualSyAndPtTrx = ({
812
+ args,
813
+ routerAddress,
814
+ }: {
815
+ args: AddLiquidityDualSyAndPtArgs;
816
+ routerAddress: Address;
817
+ }): Unwrapable<Call> => routerTrx(routerAddress, addLiquidityDualSyAndPtCalldata(args));
818
+
819
+ // =============================================================================
820
+ // ActionAddRemoveLiqV3 — remove liquidity
821
+ // =============================================================================
822
+
823
+ // ---- removeLiquiditySingleToken --------------------------------------------
824
+ // LP → token via SY. Output + limit forced clean.
825
+
826
+ export type RemoveLiquiditySingleTokenArgs = Readonly<{
827
+ receiver: Address;
828
+ market: Address;
829
+ netLpToRemove: bigint;
830
+ output: TokenOutputParams;
831
+ }>;
832
+
833
+ export const removeLiquiditySingleTokenCalldata = ({
834
+ receiver,
835
+ market,
836
+ netLpToRemove,
837
+ output,
838
+ }: RemoveLiquiditySingleTokenArgs): HexString =>
839
+ encodeFunctionData({
840
+ abi: pendleRouterAbi,
841
+ functionName: "removeLiquiditySingleToken",
842
+ args: [receiver, market, netLpToRemove, makeCleanTokenOutput(output), EMPTY_LIMIT_ORDER_DATA],
843
+ });
844
+
845
+ export const removeLiquiditySingleTokenTrx = ({
846
+ args,
847
+ routerAddress,
848
+ }: {
849
+ args: RemoveLiquiditySingleTokenArgs;
850
+ routerAddress: Address;
851
+ }): Unwrapable<Call> => routerTrx(routerAddress, removeLiquiditySingleTokenCalldata(args));
852
+
853
+ // ---- removeLiquiditySingleSy -----------------------------------------------
854
+ // LP → SY. No aggregator struct; limit forced clean.
855
+
856
+ export type RemoveLiquiditySingleSyArgs = Readonly<{
857
+ receiver: Address;
858
+ market: Address;
859
+ netLpToRemove: bigint;
860
+ minSyOut: bigint;
861
+ }>;
862
+
863
+ export const removeLiquiditySingleSyCalldata = ({
864
+ receiver,
865
+ market,
866
+ netLpToRemove,
867
+ minSyOut,
868
+ }: RemoveLiquiditySingleSyArgs): HexString =>
869
+ encodeFunctionData({
870
+ abi: pendleRouterAbi,
871
+ functionName: "removeLiquiditySingleSy",
872
+ args: [receiver, market, netLpToRemove, minSyOut, EMPTY_LIMIT_ORDER_DATA],
873
+ });
874
+
875
+ export const removeLiquiditySingleSyTrx = ({
876
+ args,
877
+ routerAddress,
878
+ }: {
879
+ args: RemoveLiquiditySingleSyArgs;
880
+ routerAddress: Address;
881
+ }): Unwrapable<Call> => routerTrx(routerAddress, removeLiquiditySingleSyCalldata(args));
882
+
883
+ // ---- removeLiquiditySinglePt -----------------------------------------------
884
+ // LP → PT. No aggregator struct; limit forced clean; needs ApproxParams.
885
+
886
+ export type RemoveLiquiditySinglePtArgs = Readonly<{
887
+ receiver: Address;
888
+ market: Address;
889
+ netLpToRemove: bigint;
890
+ minPtOut: bigint;
891
+ guess: ApproxParams;
892
+ }>;
893
+
894
+ export const removeLiquiditySinglePtCalldata = ({
895
+ receiver,
896
+ market,
897
+ netLpToRemove,
898
+ minPtOut,
899
+ guess,
900
+ }: RemoveLiquiditySinglePtArgs): HexString =>
901
+ encodeFunctionData({
902
+ abi: pendleRouterAbi,
903
+ functionName: "removeLiquiditySinglePt",
904
+ args: [receiver, market, netLpToRemove, minPtOut, guess, EMPTY_LIMIT_ORDER_DATA],
905
+ });
906
+
907
+ export const removeLiquiditySinglePtTrx = ({
908
+ args,
909
+ routerAddress,
910
+ }: {
911
+ args: RemoveLiquiditySinglePtArgs;
912
+ routerAddress: Address;
913
+ }): Unwrapable<Call> => routerTrx(routerAddress, removeLiquiditySinglePtCalldata(args));
914
+
915
+ // ---- removeLiquidityDualTokenAndPt -----------------------------------------
916
+ // LP → token + PT. Output forced clean. No LimitOrderData param.
917
+
918
+ export type RemoveLiquidityDualTokenAndPtArgs = Readonly<{
919
+ receiver: Address;
920
+ market: Address;
921
+ netLpToRemove: bigint;
922
+ output: TokenOutputParams;
923
+ minPtOut: bigint;
924
+ }>;
925
+
926
+ export const removeLiquidityDualTokenAndPtCalldata = ({
927
+ receiver,
928
+ market,
929
+ netLpToRemove,
930
+ output,
931
+ minPtOut,
932
+ }: RemoveLiquidityDualTokenAndPtArgs): HexString =>
933
+ encodeFunctionData({
934
+ abi: pendleRouterAbi,
935
+ functionName: "removeLiquidityDualTokenAndPt",
936
+ args: [receiver, market, netLpToRemove, makeCleanTokenOutput(output), minPtOut],
937
+ });
938
+
939
+ export const removeLiquidityDualTokenAndPtTrx = ({
940
+ args,
941
+ routerAddress,
942
+ }: {
943
+ args: RemoveLiquidityDualTokenAndPtArgs;
944
+ routerAddress: Address;
945
+ }): Unwrapable<Call> => routerTrx(routerAddress, removeLiquidityDualTokenAndPtCalldata(args));
946
+
947
+ // ---- removeLiquidityDualSyAndPt --------------------------------------------
948
+ // LP → SY + PT. No aggregator struct at all.
949
+
950
+ export type RemoveLiquidityDualSyAndPtArgs = Readonly<{
951
+ receiver: Address;
952
+ market: Address;
953
+ netLpToRemove: bigint;
954
+ minSyOut: bigint;
955
+ minPtOut: bigint;
956
+ }>;
957
+
958
+ export const removeLiquidityDualSyAndPtCalldata = ({
959
+ receiver,
960
+ market,
961
+ netLpToRemove,
962
+ minSyOut,
963
+ minPtOut,
964
+ }: RemoveLiquidityDualSyAndPtArgs): HexString =>
965
+ encodeFunctionData({
966
+ abi: pendleRouterAbi,
967
+ functionName: "removeLiquidityDualSyAndPt",
968
+ args: [receiver, market, netLpToRemove, minSyOut, minPtOut],
969
+ });
970
+
971
+ export const removeLiquidityDualSyAndPtTrx = ({
972
+ args,
973
+ routerAddress,
974
+ }: {
975
+ args: RemoveLiquidityDualSyAndPtArgs;
976
+ routerAddress: Address;
977
+ }): Unwrapable<Call> => routerTrx(routerAddress, removeLiquidityDualSyAndPtCalldata(args));