@uniswap/universal-router-sdk 5.2.0 → 5.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.
Files changed (58) hide show
  1. package/README.md +81 -0
  2. package/dist/cjs/src/index.d.ts +3 -0
  3. package/dist/cjs/src/index.js +6 -1
  4. package/dist/cjs/src/index.js.map +1 -1
  5. package/dist/cjs/src/swapRouter.d.ts +17 -1
  6. package/dist/cjs/src/swapRouter.js +83 -8
  7. package/dist/cjs/src/swapRouter.js.map +1 -1
  8. package/dist/cjs/src/types/encodeSwaps.d.ts +149 -0
  9. package/dist/cjs/src/types/encodeSwaps.js +3 -0
  10. package/dist/cjs/src/types/encodeSwaps.js.map +1 -0
  11. package/dist/cjs/src/utils/computeEncodeSwapsAmounts.d.ts +8 -0
  12. package/dist/cjs/src/utils/computeEncodeSwapsAmounts.js +47 -0
  13. package/dist/cjs/src/utils/computeEncodeSwapsAmounts.js.map +1 -0
  14. package/dist/cjs/src/utils/encodeSwapStep.d.ts +4 -0
  15. package/dist/cjs/src/utils/encodeSwapStep.js +61 -0
  16. package/dist/cjs/src/utils/encodeSwapStep.js.map +1 -0
  17. package/dist/cjs/src/utils/encodeV4Action.d.ts +8 -0
  18. package/dist/cjs/src/utils/encodeV4Action.js +97 -0
  19. package/dist/cjs/src/utils/encodeV4Action.js.map +1 -0
  20. package/dist/cjs/src/utils/normalizeEncodeSwapsSpec.d.ts +2 -0
  21. package/dist/cjs/src/utils/normalizeEncodeSwapsSpec.js +18 -0
  22. package/dist/cjs/src/utils/normalizeEncodeSwapsSpec.js.map +1 -0
  23. package/dist/cjs/src/utils/validateEncodeSwaps.d.ts +2 -0
  24. package/dist/cjs/src/utils/validateEncodeSwaps.js +135 -0
  25. package/dist/cjs/src/utils/validateEncodeSwaps.js.map +1 -0
  26. package/dist/esm/src/index.d.ts +3 -0
  27. package/dist/esm/src/index.js +3 -0
  28. package/dist/esm/src/index.js.map +1 -1
  29. package/dist/esm/src/swapRouter.d.ts +17 -1
  30. package/dist/esm/src/swapRouter.js +85 -10
  31. package/dist/esm/src/swapRouter.js.map +1 -1
  32. package/dist/esm/src/types/encodeSwaps.d.ts +149 -0
  33. package/dist/esm/src/types/encodeSwaps.js +2 -0
  34. package/dist/esm/src/types/encodeSwaps.js.map +1 -0
  35. package/dist/esm/src/utils/computeEncodeSwapsAmounts.d.ts +8 -0
  36. package/dist/esm/src/utils/computeEncodeSwapsAmounts.js +43 -0
  37. package/dist/esm/src/utils/computeEncodeSwapsAmounts.js.map +1 -0
  38. package/dist/esm/src/utils/encodeSwapStep.d.ts +4 -0
  39. package/dist/esm/src/utils/encodeSwapStep.js +57 -0
  40. package/dist/esm/src/utils/encodeSwapStep.js.map +1 -0
  41. package/dist/esm/src/utils/encodeV4Action.d.ts +8 -0
  42. package/dist/esm/src/utils/encodeV4Action.js +92 -0
  43. package/dist/esm/src/utils/encodeV4Action.js.map +1 -0
  44. package/dist/esm/src/utils/normalizeEncodeSwapsSpec.d.ts +2 -0
  45. package/dist/esm/src/utils/normalizeEncodeSwapsSpec.js +14 -0
  46. package/dist/esm/src/utils/normalizeEncodeSwapsSpec.js.map +1 -0
  47. package/dist/esm/src/utils/validateEncodeSwaps.d.ts +2 -0
  48. package/dist/esm/src/utils/validateEncodeSwaps.js +130 -0
  49. package/dist/esm/src/utils/validateEncodeSwaps.js.map +1 -0
  50. package/dist/types/src/index.d.ts +3 -0
  51. package/dist/types/src/swapRouter.d.ts +17 -1
  52. package/dist/types/src/types/encodeSwaps.d.ts +149 -0
  53. package/dist/types/src/utils/computeEncodeSwapsAmounts.d.ts +8 -0
  54. package/dist/types/src/utils/encodeSwapStep.d.ts +4 -0
  55. package/dist/types/src/utils/encodeV4Action.d.ts +8 -0
  56. package/dist/types/src/utils/normalizeEncodeSwapsSpec.d.ts +2 -0
  57. package/dist/types/src/utils/validateEncodeSwaps.d.ts +2 -0
  58. package/package.json +1 -1
@@ -0,0 +1,149 @@
1
+ import { BigNumberish } from 'ethers';
2
+ import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core';
3
+ import { type PathKey, type PoolKey } from '@uniswap/v4-sdk';
4
+ import { TokenTransferMode } from '../entities/actions/uniswap';
5
+ import { Permit2Permit } from '../utils/inputTokens';
6
+ import { UniversalRouterVersion } from '../utils/constants';
7
+ export type { PathKey, PoolKey };
8
+ export type Fee = {
9
+ kind: 'portion';
10
+ recipient: string;
11
+ fee: Percent;
12
+ } | {
13
+ kind: 'flat';
14
+ recipient: string;
15
+ amount: BigNumberish;
16
+ };
17
+ export type SwapSpecification = {
18
+ tradeType: TradeType;
19
+ routing: {
20
+ inputToken: Currency;
21
+ outputToken: Currency;
22
+ amount: CurrencyAmount<Currency>;
23
+ quote: CurrencyAmount<Currency>;
24
+ };
25
+ slippageTolerance: Percent;
26
+ recipient?: string;
27
+ fee?: Fee;
28
+ tokenTransferMode?: TokenTransferMode;
29
+ permit?: Permit2Permit;
30
+ chainId?: number;
31
+ deadline?: BigNumberish;
32
+ urVersion?: UniversalRouterVersion;
33
+ safeMode?: boolean;
34
+ };
35
+ export type NormalizedSwapSpecification = Omit<SwapSpecification, 'recipient' | 'tokenTransferMode' | 'urVersion' | 'safeMode'> & {
36
+ recipient: string;
37
+ tokenTransferMode: TokenTransferMode;
38
+ urVersion: UniversalRouterVersion;
39
+ safeMode: boolean;
40
+ };
41
+ export type V2SwapExactIn = {
42
+ type: 'V2_SWAP_EXACT_IN';
43
+ recipient: string;
44
+ amountIn: BigNumberish;
45
+ amountOutMin: BigNumberish;
46
+ path: string[];
47
+ minHopPriceX36?: BigNumberish[];
48
+ };
49
+ export type V2SwapExactOut = {
50
+ type: 'V2_SWAP_EXACT_OUT';
51
+ recipient: string;
52
+ amountOut: BigNumberish;
53
+ amountInMax: BigNumberish;
54
+ path: string[];
55
+ minHopPriceX36?: BigNumberish[];
56
+ };
57
+ export type V3SwapExactIn = {
58
+ type: 'V3_SWAP_EXACT_IN';
59
+ recipient: string;
60
+ amountIn: BigNumberish;
61
+ amountOutMin: BigNumberish;
62
+ path: string;
63
+ minHopPriceX36?: BigNumberish[];
64
+ };
65
+ export type V3SwapExactOut = {
66
+ type: 'V3_SWAP_EXACT_OUT';
67
+ recipient: string;
68
+ amountOut: BigNumberish;
69
+ amountInMax: BigNumberish;
70
+ path: string;
71
+ minHopPriceX36?: BigNumberish[];
72
+ };
73
+ export type V4Swap = {
74
+ type: 'V4_SWAP';
75
+ v4Actions: V4Action[];
76
+ };
77
+ export type WrapEth = {
78
+ type: 'WRAP_ETH';
79
+ recipient: string;
80
+ amount: BigNumberish;
81
+ };
82
+ export type UnwrapWeth = {
83
+ type: 'UNWRAP_WETH';
84
+ recipient: string;
85
+ amountMin: BigNumberish;
86
+ };
87
+ export type SwapStep = V2SwapExactIn | V2SwapExactOut | V3SwapExactIn | V3SwapExactOut | V4Swap | WrapEth | UnwrapWeth;
88
+ export type V4SwapExactIn = {
89
+ action: 'SWAP_EXACT_IN';
90
+ currencyIn: string;
91
+ path: PathKey[];
92
+ amountIn: BigNumberish;
93
+ amountOutMinimum: BigNumberish;
94
+ minHopPriceX36?: BigNumberish[];
95
+ };
96
+ export type V4SwapExactInSingle = {
97
+ action: 'SWAP_EXACT_IN_SINGLE';
98
+ poolKey: PoolKey;
99
+ zeroForOne: boolean;
100
+ amountIn: BigNumberish;
101
+ amountOutMinimum: BigNumberish;
102
+ minHopPriceX36?: BigNumberish;
103
+ hookData: string;
104
+ };
105
+ export type V4SwapExactOut = {
106
+ action: 'SWAP_EXACT_OUT';
107
+ currencyOut: string;
108
+ path: PathKey[];
109
+ amountOut: BigNumberish;
110
+ amountInMaximum: BigNumberish;
111
+ minHopPriceX36?: BigNumberish[];
112
+ };
113
+ export type V4SwapExactOutSingle = {
114
+ action: 'SWAP_EXACT_OUT_SINGLE';
115
+ poolKey: PoolKey;
116
+ zeroForOne: boolean;
117
+ amountOut: BigNumberish;
118
+ amountInMaximum: BigNumberish;
119
+ minHopPriceX36?: BigNumberish;
120
+ hookData: string;
121
+ };
122
+ export type V4Settle = {
123
+ action: 'SETTLE';
124
+ currency: string;
125
+ amount: BigNumberish;
126
+ };
127
+ export type V4SettleAll = {
128
+ action: 'SETTLE_ALL';
129
+ currency: string;
130
+ maxAmount: BigNumberish;
131
+ };
132
+ export type V4Take = {
133
+ action: 'TAKE';
134
+ currency: string;
135
+ recipient: string;
136
+ amount: BigNumberish;
137
+ };
138
+ export type V4TakeAll = {
139
+ action: 'TAKE_ALL';
140
+ currency: string;
141
+ minAmount: BigNumberish;
142
+ };
143
+ export type V4TakePortion = {
144
+ action: 'TAKE_PORTION';
145
+ currency: string;
146
+ recipient: string;
147
+ bips: BigNumberish;
148
+ };
149
+ export type V4Action = V4SwapExactIn | V4SwapExactInSingle | V4SwapExactOut | V4SwapExactOutSingle | V4Settle | V4SettleAll | V4Take | V4TakeAll | V4TakePortion;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=encodeSwaps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encodeSwaps.js","sourceRoot":"","sources":["../../../../src/types/encodeSwaps.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import { BigNumber } from 'ethers';
2
+ import { NormalizedSwapSpecification } from '../types/encodeSwaps';
3
+ export type EncodeSwapsAmounts = {
4
+ exactOrMaxAmountIn: BigNumber;
5
+ grossMinOrExactAmountOut: BigNumber;
6
+ netMinOrExactAmountOut: BigNumber;
7
+ };
8
+ export declare function computeEncodeSwapsAmounts(spec: NormalizedSwapSpecification): EncodeSwapsAmounts;
@@ -0,0 +1,43 @@
1
+ import { BigNumber } from 'ethers';
2
+ import { TradeType } from '@uniswap/sdk-core';
3
+ import { isAtLeastV2_1_1 } from './constants';
4
+ import { encodeFee1e18, encodeFeeBips } from './numbers';
5
+ // Slippage is applied to the quote: scaled down to a floor for exact-input output,
6
+ // scaled up to a ceiling for exact-output input. The unscaled side is the user's exact value.
7
+ // Portion fees pair with exact-input (1e18 precision on >=v2.1.1, bps on v2.0); flat fees pair with exact-output.
8
+ export function computeEncodeSwapsAmounts(spec) {
9
+ var _a, _b;
10
+ const routingAmount = BigNumber.from(spec.routing.amount.quotient.toString());
11
+ const routingQuote = BigNumber.from(spec.routing.quote.quotient.toString());
12
+ const slippageNumerator = BigNumber.from(spec.slippageTolerance.numerator.toString());
13
+ const slippageDenominator = BigNumber.from(spec.slippageTolerance.denominator.toString());
14
+ if (spec.tradeType === TradeType.EXACT_INPUT) {
15
+ const grossMinOrExactAmountOut = routingQuote
16
+ .mul(slippageDenominator)
17
+ .div(slippageDenominator.add(slippageNumerator));
18
+ if (((_a = spec.fee) === null || _a === void 0 ? void 0 : _a.kind) === 'portion') {
19
+ const feeAmount = isAtLeastV2_1_1(spec.urVersion)
20
+ ? grossMinOrExactAmountOut.mul(BigNumber.from(encodeFee1e18(spec.fee.fee))).div(BigNumber.from(10).pow(18))
21
+ : grossMinOrExactAmountOut.mul(BigNumber.from(encodeFeeBips(spec.fee.fee))).div(10000);
22
+ return {
23
+ exactOrMaxAmountIn: routingAmount,
24
+ grossMinOrExactAmountOut,
25
+ netMinOrExactAmountOut: grossMinOrExactAmountOut.sub(feeAmount),
26
+ };
27
+ }
28
+ return {
29
+ exactOrMaxAmountIn: routingAmount,
30
+ grossMinOrExactAmountOut,
31
+ netMinOrExactAmountOut: grossMinOrExactAmountOut,
32
+ };
33
+ }
34
+ const exactOrMaxAmountIn = routingQuote.mul(slippageDenominator.add(slippageNumerator)).div(slippageDenominator);
35
+ const grossMinOrExactAmountOut = routingAmount;
36
+ const netMinOrExactAmountOut = ((_b = spec.fee) === null || _b === void 0 ? void 0 : _b.kind) === 'flat' ? grossMinOrExactAmountOut.sub(BigNumber.from(spec.fee.amount)) : grossMinOrExactAmountOut;
37
+ return {
38
+ exactOrMaxAmountIn,
39
+ grossMinOrExactAmountOut,
40
+ netMinOrExactAmountOut,
41
+ };
42
+ }
43
+ //# sourceMappingURL=computeEncodeSwapsAmounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"computeEncodeSwapsAmounts.js","sourceRoot":"","sources":["../../../../src/utils/computeEncodeSwapsAmounts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAWxD,mFAAmF;AACnF,8FAA8F;AAC9F,kHAAkH;AAClH,MAAM,UAAU,yBAAyB,CAAC,IAAiC;;IACzE,MAAM,aAAa,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC7E,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC3E,MAAM,iBAAiB,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAA;IACrF,MAAM,mBAAmB,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAA;IAEzF,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,WAAW,EAAE;QAC5C,MAAM,wBAAwB,GAAG,YAAY;aAC1C,GAAG,CAAC,mBAAmB,CAAC;aACxB,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAA;QAElD,IAAI,CAAA,MAAA,IAAI,CAAC,GAAG,0CAAE,IAAI,MAAK,SAAS,EAAE;YAChC,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC/C,CAAC,CAAC,wBAAwB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC3G,CAAC,CAAC,wBAAwB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAM,CAAC,CAAA;YAEzF,OAAO;gBACL,kBAAkB,EAAE,aAAa;gBACjC,wBAAwB;gBACxB,sBAAsB,EAAE,wBAAwB,CAAC,GAAG,CAAC,SAAS,CAAC;aAChE,CAAA;SACF;QAED,OAAO;YACL,kBAAkB,EAAE,aAAa;YACjC,wBAAwB;YACxB,sBAAsB,EAAE,wBAAwB;SACjD,CAAA;KACF;IAED,MAAM,kBAAkB,GAAG,YAAY,CAAC,GAAG,CAAC,mBAAmB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAA;IAChH,MAAM,wBAAwB,GAAG,aAAa,CAAA;IAC9C,MAAM,sBAAsB,GAC1B,CAAA,MAAA,IAAI,CAAC,GAAG,0CAAE,IAAI,MAAK,MAAM,CAAC,CAAC,CAAC,wBAAwB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAA;IAEtH,OAAO;QACL,kBAAkB;QAClB,wBAAwB;QACxB,sBAAsB;KACvB,CAAA;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { UniversalRouterVersion } from './constants';
2
+ import { RoutePlanner } from './routerCommands';
3
+ import { SwapStep } from '../types/encodeSwaps';
4
+ export declare function encodeSwapStep(planner: RoutePlanner, step: SwapStep, urVersion?: UniversalRouterVersion): void;
@@ -0,0 +1,57 @@
1
+ import { V4Planner } from '@uniswap/v4-sdk';
2
+ import { isAtLeastV2_1_1 } from './constants';
3
+ import { CommandType } from './routerCommands';
4
+ import { encodeV4Action, toV4URVersion } from './encodeV4Action';
5
+ // V2/V3 swap params hardcode payerIsUser=false; encodeSwaps pulls funds into the router first via PERMIT2_TRANSFER_FROM
6
+ export function encodeSwapStep(planner, step, urVersion) {
7
+ var _a, _b, _c, _d;
8
+ const useV2_1_1 = isAtLeastV2_1_1(urVersion);
9
+ switch (step.type) {
10
+ case 'V2_SWAP_EXACT_IN': {
11
+ const params = [step.recipient, step.amountIn, step.amountOutMin, step.path, false];
12
+ if (useV2_1_1)
13
+ params.push((_a = step.minHopPriceX36) !== null && _a !== void 0 ? _a : []);
14
+ planner.addCommand(CommandType.V2_SWAP_EXACT_IN, params, false, urVersion);
15
+ return;
16
+ }
17
+ case 'V2_SWAP_EXACT_OUT': {
18
+ const params = [step.recipient, step.amountOut, step.amountInMax, step.path, false];
19
+ if (useV2_1_1)
20
+ params.push((_b = step.minHopPriceX36) !== null && _b !== void 0 ? _b : []);
21
+ planner.addCommand(CommandType.V2_SWAP_EXACT_OUT, params, false, urVersion);
22
+ return;
23
+ }
24
+ case 'V3_SWAP_EXACT_IN': {
25
+ const params = [step.recipient, step.amountIn, step.amountOutMin, step.path, false];
26
+ if (useV2_1_1)
27
+ params.push((_c = step.minHopPriceX36) !== null && _c !== void 0 ? _c : []);
28
+ planner.addCommand(CommandType.V3_SWAP_EXACT_IN, params, false, urVersion);
29
+ return;
30
+ }
31
+ case 'V3_SWAP_EXACT_OUT': {
32
+ const params = [step.recipient, step.amountOut, step.amountInMax, step.path, false];
33
+ if (useV2_1_1)
34
+ params.push((_d = step.minHopPriceX36) !== null && _d !== void 0 ? _d : []);
35
+ planner.addCommand(CommandType.V3_SWAP_EXACT_OUT, params, false, urVersion);
36
+ return;
37
+ }
38
+ case 'V4_SWAP': {
39
+ const v4Planner = new V4Planner();
40
+ for (const v4Action of step.v4Actions) {
41
+ const encoded = encodeV4Action(v4Action, urVersion);
42
+ v4Planner.addAction(encoded.action, encoded.params, toV4URVersion(urVersion));
43
+ }
44
+ planner.addCommand(CommandType.V4_SWAP, [v4Planner.finalize()], false, urVersion);
45
+ return;
46
+ }
47
+ case 'WRAP_ETH':
48
+ planner.addCommand(CommandType.WRAP_ETH, [step.recipient, step.amount], false, urVersion);
49
+ return;
50
+ case 'UNWRAP_WETH':
51
+ planner.addCommand(CommandType.UNWRAP_WETH, [step.recipient, step.amountMin], false, urVersion);
52
+ return;
53
+ default:
54
+ throw new Error(`Unknown swap step type: ${step.type}`);
55
+ }
56
+ }
57
+ //# sourceMappingURL=encodeSwapStep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encodeSwapStep.js","sourceRoot":"","sources":["../../../../src/utils/encodeSwapStep.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { Actions, URVersion } from '@uniswap/v4-sdk';
2
+ import { UniversalRouterVersion } from './constants';
3
+ import { V4Action } from '../types/encodeSwaps';
4
+ export declare function toV4URVersion(version?: UniversalRouterVersion): URVersion;
5
+ export declare function encodeV4Action(v4Action: V4Action, urVersion?: UniversalRouterVersion): {
6
+ action: Actions;
7
+ params: any[];
8
+ };
@@ -0,0 +1,92 @@
1
+ import { Actions, URVersion } from '@uniswap/v4-sdk';
2
+ import { UniversalRouterVersion, isAtLeastV2_1_1 } from './constants';
3
+ const ACTION_NAME_TO_ENUM = Object.fromEntries(Object.entries(Actions).filter(([key]) => isNaN(Number(key))));
4
+ const V4_UR_VERSION_MAP = {
5
+ [UniversalRouterVersion.V2_0]: URVersion.V2_0,
6
+ [UniversalRouterVersion.V2_1_1]: URVersion.V2_1_1,
7
+ };
8
+ export function toV4URVersion(version) {
9
+ if (version === undefined)
10
+ return URVersion.V2_0;
11
+ const mapped = V4_UR_VERSION_MAP[version];
12
+ if (!mapped)
13
+ throw new Error(`No v4-sdk URVersion mapping for UniversalRouterVersion: ${version}`);
14
+ return mapped;
15
+ }
16
+ export function encodeV4Action(v4Action, urVersion) {
17
+ var _a, _b, _c, _d;
18
+ const action = ACTION_NAME_TO_ENUM[v4Action.action];
19
+ if (action === undefined)
20
+ throw new Error(`Unknown V4 action: ${v4Action.action}`);
21
+ const useV2_1_1 = isAtLeastV2_1_1(urVersion);
22
+ switch (v4Action.action) {
23
+ case 'SWAP_EXACT_IN':
24
+ return {
25
+ action,
26
+ params: [
27
+ {
28
+ currencyIn: v4Action.currencyIn,
29
+ path: v4Action.path,
30
+ ...(useV2_1_1 && { minHopPriceX36: (_a = v4Action.minHopPriceX36) !== null && _a !== void 0 ? _a : [] }),
31
+ amountIn: v4Action.amountIn,
32
+ amountOutMinimum: v4Action.amountOutMinimum,
33
+ },
34
+ ],
35
+ };
36
+ case 'SWAP_EXACT_IN_SINGLE':
37
+ return {
38
+ action,
39
+ params: [
40
+ {
41
+ poolKey: v4Action.poolKey,
42
+ zeroForOne: v4Action.zeroForOne,
43
+ amountIn: v4Action.amountIn,
44
+ amountOutMinimum: v4Action.amountOutMinimum,
45
+ ...(useV2_1_1 && { minHopPriceX36: (_b = v4Action.minHopPriceX36) !== null && _b !== void 0 ? _b : 0 }),
46
+ hookData: v4Action.hookData,
47
+ },
48
+ ],
49
+ };
50
+ case 'SWAP_EXACT_OUT':
51
+ return {
52
+ action,
53
+ params: [
54
+ {
55
+ currencyOut: v4Action.currencyOut,
56
+ path: v4Action.path,
57
+ ...(useV2_1_1 && { minHopPriceX36: (_c = v4Action.minHopPriceX36) !== null && _c !== void 0 ? _c : [] }),
58
+ amountOut: v4Action.amountOut,
59
+ amountInMaximum: v4Action.amountInMaximum,
60
+ },
61
+ ],
62
+ };
63
+ case 'SWAP_EXACT_OUT_SINGLE':
64
+ return {
65
+ action,
66
+ params: [
67
+ {
68
+ poolKey: v4Action.poolKey,
69
+ zeroForOne: v4Action.zeroForOne,
70
+ amountOut: v4Action.amountOut,
71
+ amountInMaximum: v4Action.amountInMaximum,
72
+ ...(useV2_1_1 && { minHopPriceX36: (_d = v4Action.minHopPriceX36) !== null && _d !== void 0 ? _d : 0 }),
73
+ hookData: v4Action.hookData,
74
+ },
75
+ ],
76
+ };
77
+ case 'SETTLE':
78
+ // payerIsUser=false: same router-custody model as encodeSwapStep — funds are already in the router
79
+ return { action, params: [v4Action.currency, v4Action.amount, false] };
80
+ case 'SETTLE_ALL':
81
+ return { action, params: [v4Action.currency, v4Action.maxAmount] };
82
+ case 'TAKE':
83
+ return { action, params: [v4Action.currency, v4Action.recipient, v4Action.amount] };
84
+ case 'TAKE_ALL':
85
+ return { action, params: [v4Action.currency, v4Action.minAmount] };
86
+ case 'TAKE_PORTION':
87
+ return { action, params: [v4Action.currency, v4Action.recipient, v4Action.bips] };
88
+ default:
89
+ throw new Error(`Unhandled V4 action: ${v4Action.action}`);
90
+ }
91
+ }
92
+ //# sourceMappingURL=encodeV4Action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encodeV4Action.js","sourceRoot":"","sources":["../../../../src/utils/encodeV4Action.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { NormalizedSwapSpecification, SwapSpecification } from '../types/encodeSwaps';
2
+ export declare function normalizeEncodeSwapsSpec(spec: SwapSpecification): NormalizedSwapSpecification;
@@ -0,0 +1,14 @@
1
+ import { TokenTransferMode } from '../entities/actions/uniswap';
2
+ import { SENDER_AS_RECIPIENT, UniversalRouterVersion } from './constants';
3
+ // Fills the four optional fields that `validateEncodeSwaps` and `computeEncodeSwapsAmounts` require.
4
+ export function normalizeEncodeSwapsSpec(spec) {
5
+ var _a, _b, _c, _d;
6
+ return {
7
+ ...spec,
8
+ recipient: (_a = spec.recipient) !== null && _a !== void 0 ? _a : SENDER_AS_RECIPIENT,
9
+ tokenTransferMode: (_b = spec.tokenTransferMode) !== null && _b !== void 0 ? _b : TokenTransferMode.Permit2,
10
+ urVersion: (_c = spec.urVersion) !== null && _c !== void 0 ? _c : UniversalRouterVersion.V2_0,
11
+ safeMode: (_d = spec.safeMode) !== null && _d !== void 0 ? _d : false,
12
+ };
13
+ }
14
+ //# sourceMappingURL=normalizeEncodeSwapsSpec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalizeEncodeSwapsSpec.js","sourceRoot":"","sources":["../../../../src/utils/normalizeEncodeSwapsSpec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAE/D,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAEzE,qGAAqG;AACrG,MAAM,UAAU,wBAAwB,CAAC,IAAuB;;IAC9D,OAAO;QACL,GAAG,IAAI;QACP,SAAS,EAAE,MAAA,IAAI,CAAC,SAAS,mCAAI,mBAAmB;QAChD,iBAAiB,EAAE,MAAA,IAAI,CAAC,iBAAiB,mCAAI,iBAAiB,CAAC,OAAO;QACtE,SAAS,EAAE,MAAA,IAAI,CAAC,SAAS,mCAAI,sBAAsB,CAAC,IAAI;QACxD,QAAQ,EAAE,MAAA,IAAI,CAAC,QAAQ,mCAAI,KAAK;KACjC,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { NormalizedSwapSpecification, SwapStep } from '../types/encodeSwaps';
2
+ export declare function validateEncodeSwaps(spec: NormalizedSwapSpecification, swapSteps: SwapStep[]): void;
@@ -0,0 +1,130 @@
1
+ import { BigNumber } from 'ethers';
2
+ import invariant from 'tiny-invariant';
3
+ import { TradeType } from '@uniswap/sdk-core';
4
+ import { TokenTransferMode } from '../entities/actions/uniswap';
5
+ import { ROUTER_AS_RECIPIENT, SENDER_AS_RECIPIENT, UniversalRouterVersion, ZERO_ADDRESS } from './constants';
6
+ // V3 path: 20-byte address + N × (3-byte fee + 20-byte address); minimum is 43 bytes (single hop, N=1)
7
+ // Returns N or undefined if malformed
8
+ function getV3HopCount(path) {
9
+ if (!path.startsWith('0x'))
10
+ return undefined;
11
+ const byteLength = (path.length - 2) / 2;
12
+ if (byteLength < 43)
13
+ return undefined;
14
+ const variableSegmentLength = byteLength - 20;
15
+ if (variableSegmentLength < 23 || variableSegmentLength % 23 !== 0)
16
+ return undefined;
17
+ return variableSegmentLength / 23;
18
+ }
19
+ function hasV4MinHopPriceX36(action) {
20
+ switch (action.action) {
21
+ case 'SWAP_EXACT_IN':
22
+ case 'SWAP_EXACT_OUT':
23
+ case 'SWAP_EXACT_IN_SINGLE':
24
+ case 'SWAP_EXACT_OUT_SINGLE':
25
+ return action.minHopPriceX36 !== undefined;
26
+ default:
27
+ return false;
28
+ }
29
+ }
30
+ function validateV4HopCounts(actions) {
31
+ for (const action of actions) {
32
+ switch (action.action) {
33
+ case 'SWAP_EXACT_IN':
34
+ case 'SWAP_EXACT_OUT':
35
+ invariant(!action.minHopPriceX36 || action.minHopPriceX36.length === action.path.length, 'V4_MIN_HOP_PRICE_X36_LENGTH_MISMATCH');
36
+ break;
37
+ default:
38
+ break;
39
+ }
40
+ }
41
+ }
42
+ function assertRouterRecipient(recipient) {
43
+ invariant(recipient === ROUTER_AS_RECIPIENT, 'STEP_RECIPIENT_MUST_BE_ROUTER');
44
+ }
45
+ function assertRouterActionRecipient(recipient) {
46
+ invariant(recipient === ROUTER_AS_RECIPIENT, 'V4_ACTION_RECIPIENT_MUST_BE_ROUTER');
47
+ }
48
+ // V4 actions that take a recipient must use router custody so the SDK's settlement sweeps see the funds
49
+ function validateV4Recipients(actions) {
50
+ for (const action of actions) {
51
+ switch (action.action) {
52
+ case 'TAKE':
53
+ case 'TAKE_PORTION':
54
+ assertRouterActionRecipient(action.recipient);
55
+ break;
56
+ default:
57
+ break;
58
+ }
59
+ }
60
+ }
61
+ export function validateEncodeSwaps(spec, swapSteps) {
62
+ var _a, _b, _c, _d;
63
+ invariant(swapSteps.length > 0, 'EMPTY_SWAP_STEPS');
64
+ const amountCurrency = spec.routing.amount.currency.wrapped;
65
+ const quoteCurrency = spec.routing.quote.currency.wrapped;
66
+ const inputCurrency = spec.routing.inputToken.wrapped;
67
+ const outputCurrency = spec.routing.outputToken.wrapped;
68
+ invariant(!spec.slippageTolerance.lessThan(0), 'SLIPPAGE_TOLERANCE');
69
+ invariant(spec.recipient !== ZERO_ADDRESS, 'RECIPIENT_CANNOT_BE_ZERO');
70
+ invariant(spec.recipient !== ROUTER_AS_RECIPIENT, 'RECIPIENT_CANNOT_BE_ROUTER');
71
+ // routing.amount is on the exact side of the trade; routing.quote is on the slippage side
72
+ if (spec.tradeType === TradeType.EXACT_INPUT) {
73
+ invariant(amountCurrency.equals(inputCurrency), 'INVALID_ROUTING_AMOUNT_CURRENCY');
74
+ invariant(quoteCurrency.equals(outputCurrency), 'INVALID_ROUTING_QUOTE_CURRENCY');
75
+ }
76
+ else {
77
+ invariant(amountCurrency.equals(outputCurrency), 'INVALID_ROUTING_AMOUNT_CURRENCY');
78
+ invariant(quoteCurrency.equals(inputCurrency), 'INVALID_ROUTING_QUOTE_CURRENCY');
79
+ }
80
+ // ApproveProxy ingress lives upstream in the proxy contract: needs chain id, ERC20 input, no permit2, explicit recipient
81
+ if (spec.tokenTransferMode === TokenTransferMode.ApproveProxy) {
82
+ invariant(!!spec.chainId, 'PROXY_MISSING_CHAIN_ID');
83
+ invariant(!spec.routing.inputToken.isNative, 'PROXY_NATIVE_INPUT');
84
+ invariant(!spec.permit, 'PROXY_PERMIT_CONFLICT');
85
+ invariant(spec.recipient !== SENDER_AS_RECIPIENT, 'PROXY_EXPLICIT_RECIPIENT_REQUIRED');
86
+ }
87
+ // permit2 is ERC20-only; native input pays via msg.value
88
+ invariant(!(spec.routing.inputToken.isNative && spec.permit), 'NATIVE_INPUT_PERMIT');
89
+ // portion fees pair with exact-input (% of variable output); flat fees pair with exact-output (fixed deduction from the target)
90
+ invariant(!(((_a = spec.fee) === null || _a === void 0 ? void 0 : _a.kind) === 'portion' && spec.tradeType !== TradeType.EXACT_INPUT), 'INVALID_PORTION_FEE_TRADE_TYPE');
91
+ invariant(!(((_b = spec.fee) === null || _b === void 0 ? void 0 : _b.kind) === 'flat' && spec.tradeType !== TradeType.EXACT_OUTPUT), 'INVALID_FLAT_FEE_TRADE_TYPE');
92
+ invariant(!(((_c = spec.fee) === null || _c === void 0 ? void 0 : _c.kind) === 'flat' &&
93
+ BigNumber.from(spec.fee.amount).gt(BigNumber.from(spec.routing.amount.quotient.toString()))), 'FLAT_FEE_GT_AMOUNT');
94
+ // v2.0 PAY_PORTION takes whole bps; fractional bps need >=v2.1.1's PAY_PORTION_FULL_PRECISION
95
+ invariant(!(((_d = spec.fee) === null || _d === void 0 ? void 0 : _d.kind) === 'portion' &&
96
+ spec.urVersion === UniversalRouterVersion.V2_0 &&
97
+ !spec.fee.fee.multiply(10000).remainder.equalTo(0)), 'FRACTIONAL_BPS_PORTION_FEE_UNSUPPORTED_ON_V2_0');
98
+ // per-step: capability-gate by UR version, recipients must be router custody, per-hop arrays must match hop counts
99
+ for (const step of swapSteps) {
100
+ if (spec.urVersion === UniversalRouterVersion.V2_0) {
101
+ invariant(!('minHopPriceX36' in step) || step.minHopPriceX36 === undefined, 'MIN_HOP_PRICE_X36_UNSUPPORTED_ON_V2_0');
102
+ invariant(!(step.type === 'V4_SWAP' && step.v4Actions.some(hasV4MinHopPriceX36)), 'MIN_HOP_PRICE_X36_UNSUPPORTED_ON_V2_0');
103
+ }
104
+ switch (step.type) {
105
+ case 'V2_SWAP_EXACT_IN':
106
+ case 'V2_SWAP_EXACT_OUT':
107
+ assertRouterRecipient(step.recipient);
108
+ invariant(!step.minHopPriceX36 || step.minHopPriceX36.length === step.path.length - 1, 'V2_MIN_HOP_PRICE_X36_LENGTH_MISMATCH');
109
+ break;
110
+ case 'V3_SWAP_EXACT_IN':
111
+ case 'V3_SWAP_EXACT_OUT': {
112
+ assertRouterRecipient(step.recipient);
113
+ const hopCount = getV3HopCount(step.path);
114
+ invariant(hopCount === undefined || !step.minHopPriceX36 || step.minHopPriceX36.length === hopCount, 'V3_MIN_HOP_PRICE_X36_LENGTH_MISMATCH');
115
+ break;
116
+ }
117
+ case 'WRAP_ETH':
118
+ case 'UNWRAP_WETH':
119
+ assertRouterRecipient(step.recipient);
120
+ break;
121
+ case 'V4_SWAP':
122
+ validateV4HopCounts(step.v4Actions);
123
+ validateV4Recipients(step.v4Actions);
124
+ break;
125
+ default:
126
+ break;
127
+ }
128
+ }
129
+ }
130
+ //# sourceMappingURL=validateEncodeSwaps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateEncodeSwaps.js","sourceRoot":"","sources":["../../../../src/utils/validateEncodeSwaps.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  export { SwapRouter } from './swapRouter';
2
2
  export type { MigrateV3ToV4Options, SignedRouteOptions, EIP712Payload } from './swapRouter';
3
+ export * from './types/encodeSwaps';
3
4
  export * from './entities';
4
5
  export * from './utils/routerTradeAdapter';
5
6
  export { RoutePlanner, CommandType, COMMAND_DEFINITION, Parser, Subparser } from './utils/routerCommands';
@@ -8,4 +9,6 @@ export { UNIVERSAL_ROUTER_CREATION_BLOCK, UNIVERSAL_ROUTER_ADDRESS, SWAP_PROXY_A
8
9
  export { CommandParser, GenericCommandParser } from './utils/commandParser';
9
10
  export type { UniversalRouterCommand, UniversalRouterCall, Param, CommandsDefinition } from './utils/commandParser';
10
11
  export type { Permit2Permit } from './utils/inputTokens';
12
+ export { normalizeEncodeSwapsSpec } from './utils/normalizeEncodeSwapsSpec';
13
+ export { validateEncodeSwaps } from './utils/validateEncodeSwaps';
11
14
  export { NONCE_SKIP_CHECK, generateNonce, EXECUTE_SIGNED_TYPES, getUniversalRouterDomain } from './utils/eip712';
@@ -6,6 +6,7 @@ import { Trade as RouterTrade } from '@uniswap/router-sdk';
6
6
  import { Currency, TradeType } from '@uniswap/sdk-core';
7
7
  import { SwapOptions } from './entities/actions/uniswap';
8
8
  import { AcrossV4DepositV3Params } from './entities/actions/across';
9
+ import { SwapSpecification, SwapStep } from './types/encodeSwaps';
9
10
  import { TypedDataDomain, TypedDataField } from '@ethersproject/abstract-signer';
10
11
  export type SwapRouterConfig = {
11
12
  sender?: string;
@@ -40,6 +41,20 @@ export declare abstract class SwapRouter {
40
41
  static INTERFACE: Interface;
41
42
  static PROXY_INTERFACE: Interface;
42
43
  static swapCallParameters(trades: RouterTrade<Currency, Currency, TradeType>, options: SwapOptions, bridgeOptions?: AcrossV4DepositV3Params[]): MethodParameters;
44
+ /**
45
+ * Encodes router-provided swap steps inside the SDK safety envelope.
46
+ *
47
+ * Routers own `swapSteps` (V2/V3/V4 swaps, plus any `WRAP_ETH` / `UNWRAP_WETH` required by the route).
48
+ * The SDK owns ingress, fees, final settlement, exact-output refund, and optional `safeMode`.
49
+ *
50
+ * Router contract: end with final output in `spec.routing.outputToken`; for `EXACT_OUTPUT`, unused input
51
+ * must end in `spec.routing.inputToken`. Don't include a top-level `SWEEP` — the SDK appends settlement,
52
+ * refund, and safeMode sweeps itself.
53
+ *
54
+ * Router custody with `payerIsUser = false` is deliberate for safety, even if it costs an extra command
55
+ * or transfer; the SDK does not infer route topology on behalf of routers.
56
+ */
57
+ static encodeSwaps(spec: SwapSpecification, swapSteps: SwapStep[]): MethodParameters;
43
58
  /**
44
59
  * Generate EIP712 payload for signed execution (no signing performed)
45
60
  * Decodes existing execute() calldata and prepares it for signing
@@ -80,8 +95,9 @@ export declare abstract class SwapRouter {
80
95
  */
81
96
  private static encodePlan;
82
97
  /**
83
- * Encodes a planned route into calldata targeting the SwapProxy contract.
98
+ * Wraps an inner UR plan in calldata targeting the SwapProxy contract.
84
99
  * The proxy pulls ERC20 tokens from the user into the UR, then executes commands.
85
100
  */
86
101
  private static encodeProxyPlan;
102
+ private static encodeProxyCall;
87
103
  }