@mento-protocol/mento-sdk 3.2.6-beta.3 → 3.2.7-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache/routes.js +1401 -849
- package/dist/cache/tokens.js +43 -15
- package/dist/esm/cache/routes.js +1401 -849
- package/dist/esm/cache/tokens.js +43 -15
- package/dist/esm/services/liquidity/zapHelpers.js +61 -0
- package/dist/esm/services/liquidity/zapIn.js +22 -3
- package/dist/services/liquidity/zapHelpers.d.ts +34 -0
- package/dist/services/liquidity/zapHelpers.js +63 -0
- package/dist/services/liquidity/zapIn.js +21 -2
- package/package.json +7 -1
package/dist/esm/cache/tokens.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
// Generated on 2026-04-
|
|
2
|
+
// Generated on 2026-04-27T16:44:41.707Z
|
|
3
3
|
/**
|
|
4
4
|
* Enum of all token symbols across all supported chains
|
|
5
5
|
*/
|
|
@@ -68,6 +68,18 @@ export const cachedTokens = {
|
|
|
68
68
|
symbol: TokenSymbol.EURm,
|
|
69
69
|
name: 'Mento Euro',
|
|
70
70
|
decimals: 18,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
address: '0x22f6A6752800eAB67b84748FeFc3cC658384aF72',
|
|
74
|
+
symbol: TokenSymbol.JPYm,
|
|
75
|
+
name: 'Mento Japanese Yen',
|
|
76
|
+
decimals: 18,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
address: '0xF64e91fFEf7ef43aA314F0Bc2AC39f770797990C',
|
|
80
|
+
symbol: TokenSymbol.CHFm,
|
|
81
|
+
name: 'Mento Swiss Franc',
|
|
82
|
+
decimals: 18,
|
|
71
83
|
}
|
|
72
84
|
],
|
|
73
85
|
// Chain 10143
|
|
@@ -107,6 +119,18 @@ export const cachedTokens = {
|
|
|
107
119
|
symbol: TokenSymbol.EURm,
|
|
108
120
|
name: 'Mento Euro',
|
|
109
121
|
decimals: 18,
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
address: '0x377755da4994c2cfE21b39bbCE7211eab6f5FCC1',
|
|
125
|
+
symbol: TokenSymbol.JPYm,
|
|
126
|
+
name: 'Mento Japanese Yen',
|
|
127
|
+
decimals: 18,
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
address: '0xCD8f6950359795eb4688AC18d1e9BB88fa111eEe',
|
|
131
|
+
symbol: TokenSymbol.CHFm,
|
|
132
|
+
name: 'Mento Swiss Franc',
|
|
133
|
+
decimals: 18,
|
|
110
134
|
}
|
|
111
135
|
],
|
|
112
136
|
// Chain 42220
|
|
@@ -153,6 +177,18 @@ export const cachedTokens = {
|
|
|
153
177
|
name: 'Axelar Wrapped EUROC',
|
|
154
178
|
decimals: 6,
|
|
155
179
|
},
|
|
180
|
+
{
|
|
181
|
+
address: '0xc45eCF20f3CD864B32D9794d6f76814aE8892e20',
|
|
182
|
+
symbol: TokenSymbol.JPYm,
|
|
183
|
+
name: 'Mento Japanese Yen',
|
|
184
|
+
decimals: 18,
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
address: '0xb55a79F398E759E43C95b979163f30eC87Ee131D',
|
|
188
|
+
symbol: TokenSymbol.CHFm,
|
|
189
|
+
name: 'Mento Swiss Franc',
|
|
190
|
+
decimals: 18,
|
|
191
|
+
},
|
|
156
192
|
{
|
|
157
193
|
address: '0xfAeA5F3404bbA20D3cc2f8C4B0A888F55a3c7313',
|
|
158
194
|
symbol: TokenSymbol.GHSm,
|
|
@@ -171,12 +207,6 @@ export const cachedTokens = {
|
|
|
171
207
|
name: 'Mento Australian Dollar',
|
|
172
208
|
decimals: 18,
|
|
173
209
|
},
|
|
174
|
-
{
|
|
175
|
-
address: '0xb55a79F398E759E43C95b979163f30eC87Ee131D',
|
|
176
|
-
symbol: TokenSymbol.CHFm,
|
|
177
|
-
name: 'Mento Swiss Franc',
|
|
178
|
-
decimals: 18,
|
|
179
|
-
},
|
|
180
210
|
{
|
|
181
211
|
address: '0xE2702Bd97ee33c88c8f6f92DA3B733608aa76F71',
|
|
182
212
|
symbol: TokenSymbol.NGNm,
|
|
@@ -201,12 +231,6 @@ export const cachedTokens = {
|
|
|
201
231
|
name: 'Mento Philippine Peso',
|
|
202
232
|
decimals: 18,
|
|
203
233
|
},
|
|
204
|
-
{
|
|
205
|
-
address: '0xc45eCF20f3CD864B32D9794d6f76814aE8892e20',
|
|
206
|
-
symbol: TokenSymbol.JPYm,
|
|
207
|
-
name: 'Mento Japanese Yen',
|
|
208
|
-
decimals: 18,
|
|
209
|
-
},
|
|
210
234
|
{
|
|
211
235
|
address: '0x8A567e2aE79CA692Bd748aB832081C45de4041eA',
|
|
212
236
|
symbol: TokenSymbol.COPm,
|
|
@@ -356,6 +380,8 @@ export const TOKEN_ADDRESSES_BY_CHAIN = {
|
|
|
356
380
|
[TokenSymbol.AUSD]: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',
|
|
357
381
|
[TokenSymbol.USDT0]: '0xe7cd86e13AC4309349F30B3435a9d337750fC82D',
|
|
358
382
|
[TokenSymbol.EURm]: '0x4D502d735B4C574B487Ed641ae87cEaE884731C7',
|
|
383
|
+
[TokenSymbol.JPYm]: '0x22f6A6752800eAB67b84748FeFc3cC658384aF72',
|
|
384
|
+
[TokenSymbol.CHFm]: '0xF64e91fFEf7ef43aA314F0Bc2AC39f770797990C',
|
|
359
385
|
},
|
|
360
386
|
10143: {
|
|
361
387
|
[TokenSymbol.GBPm]: '0x04de554E875c9797dC4ceBd834A9e99fa8fD5Df9',
|
|
@@ -364,6 +390,8 @@ export const TOKEN_ADDRESSES_BY_CHAIN = {
|
|
|
364
390
|
[TokenSymbol.AUSD]: '0x502E67D3fE9302A5e4Ec1CFCDdbD6F34F9B9484B',
|
|
365
391
|
[TokenSymbol.USDT0]: '0xC304EE1876c32d1A194558B1000bE4842F960dF9',
|
|
366
392
|
[TokenSymbol.EURm]: '0x666D0a83cDbf3eC62bDb624d9bFcD8F6345Ba7D0',
|
|
393
|
+
[TokenSymbol.JPYm]: '0x377755da4994c2cfE21b39bbCE7211eab6f5FCC1',
|
|
394
|
+
[TokenSymbol.CHFm]: '0xCD8f6950359795eb4688AC18d1e9BB88fa111eEe',
|
|
367
395
|
},
|
|
368
396
|
42220: {
|
|
369
397
|
[TokenSymbol.GBPm]: '0xCCF663b1fF11028f0b19058d0f7B674004a40746',
|
|
@@ -373,15 +401,15 @@ export const TOKEN_ADDRESSES_BY_CHAIN = {
|
|
|
373
401
|
[TokenSymbol.USD_]: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e',
|
|
374
402
|
[TokenSymbol.EURm]: '0xD8763CBa276a3738E6DE85b4b3bF5FDed6D6cA73',
|
|
375
403
|
[TokenSymbol.axlEUROC]: '0x061cc5a2C863E0C1Cb404006D559dB18A34C762d',
|
|
404
|
+
[TokenSymbol.JPYm]: '0xc45eCF20f3CD864B32D9794d6f76814aE8892e20',
|
|
405
|
+
[TokenSymbol.CHFm]: '0xb55a79F398E759E43C95b979163f30eC87Ee131D',
|
|
376
406
|
[TokenSymbol.GHSm]: '0xfAeA5F3404bbA20D3cc2f8C4B0A888F55a3c7313',
|
|
377
407
|
[TokenSymbol.ZARm]: '0x4c35853A3B4e647fD266f4de678dCc8fEC410BF6',
|
|
378
408
|
[TokenSymbol.AUDm]: '0x7175504C455076F15c04A2F90a8e352281F492F9',
|
|
379
|
-
[TokenSymbol.CHFm]: '0xb55a79F398E759E43C95b979163f30eC87Ee131D',
|
|
380
409
|
[TokenSymbol.NGNm]: '0xE2702Bd97ee33c88c8f6f92DA3B733608aa76F71',
|
|
381
410
|
[TokenSymbol.KESm]: '0x456a3D042C0DbD3db53D5489e98dFb038553B0d0',
|
|
382
411
|
[TokenSymbol.CADm]: '0xff4Ab19391af240c311c54200a492233052B6325',
|
|
383
412
|
[TokenSymbol.PHPm]: '0x105d4A9306D2E55a71d2Eb95B81553AE1dC20d7B',
|
|
384
|
-
[TokenSymbol.JPYm]: '0xc45eCF20f3CD864B32D9794d6f76814aE8892e20',
|
|
385
413
|
[TokenSymbol.COPm]: '0x8A567e2aE79CA692Bd748aB832081C45de4041eA',
|
|
386
414
|
[TokenSymbol.BRLm]: '0xe8537a3d056DA446677B9E9d6c5dB704EaAb4787',
|
|
387
415
|
[TokenSymbol.XOFm]: '0x73F93dcc49cB8A239e2032663e9475dd5ef29A08',
|
|
@@ -83,6 +83,67 @@ export function splitAmount(amountIn, splitRatio) {
|
|
|
83
83
|
const amountB = amountIn - amountA;
|
|
84
84
|
return { amountA, amountB };
|
|
85
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Off-chain mirror of Router.sol's quoteAddLiquidity / _quoteZapLiquidity logic.
|
|
88
|
+
*
|
|
89
|
+
* Given desired amounts and pool reserves, returns the (amountA, amountB) the
|
|
90
|
+
* router will actually deposit when adding liquidity. Used to predict the exact
|
|
91
|
+
* `amountAMin` / `amountBMin` the contract will check against post-swap reserves.
|
|
92
|
+
*
|
|
93
|
+
* @param amountADesired - Desired amount of tokenA
|
|
94
|
+
* @param amountBDesired - Desired amount of tokenB
|
|
95
|
+
* @param reserveA - Reserve of tokenA at the moment liquidity is added
|
|
96
|
+
* @param reserveB - Reserve of tokenB at the moment liquidity is added
|
|
97
|
+
*/
|
|
98
|
+
export function quoteAddLiquidityFromReserves(amountADesired, amountBDesired, reserveA, reserveB) {
|
|
99
|
+
if (reserveA === 0n && reserveB === 0n) {
|
|
100
|
+
return { amountA: amountADesired, amountB: amountBDesired };
|
|
101
|
+
}
|
|
102
|
+
if (reserveA === 0n || reserveB === 0n) {
|
|
103
|
+
// Mirrors Router.sol's InsufficientLiquidity revert. Caller can fall back.
|
|
104
|
+
return { amountA: 0n, amountB: 0n };
|
|
105
|
+
}
|
|
106
|
+
const amountBOptimal = (amountADesired * reserveB) / reserveA;
|
|
107
|
+
if (amountBOptimal <= amountBDesired) {
|
|
108
|
+
return { amountA: amountADesired, amountB: amountBOptimal };
|
|
109
|
+
}
|
|
110
|
+
const amountAOptimal = (amountBDesired * reserveA) / reserveB;
|
|
111
|
+
return { amountA: amountAOptimal, amountB: amountBDesired };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Computes the net delta a single-hop zap swap applies to a target pool's
|
|
115
|
+
* reserves. Returns `{delta0, delta1}` to add to the pool's pre-swap reserves
|
|
116
|
+
* to obtain the reserves the router will see when it runs `_quoteZapLiquidity`.
|
|
117
|
+
*
|
|
118
|
+
* Only single-hop routes whose factory matches the target pool's factory and
|
|
119
|
+
* whose `(from, to)` are `(token0, token1)` (in either direction) are
|
|
120
|
+
* considered. Multi-hop routes and routes through other pools have no effect
|
|
121
|
+
* on the target pool's reserves and return `{0, 0}`.
|
|
122
|
+
*
|
|
123
|
+
* Note: Multi-hop routes that traverse the target pool as an intermediate hop
|
|
124
|
+
* are intentionally not handled here — they are uncommon for single-sided zaps
|
|
125
|
+
* and would require per-hop amounts from `getAmountsOut`.
|
|
126
|
+
*/
|
|
127
|
+
export function computeTargetPoolImpact(routes, amountIn, amountOut, token0, token1, factoryAddr) {
|
|
128
|
+
if (routes.length !== 1) {
|
|
129
|
+
return { delta0: 0n, delta1: 0n };
|
|
130
|
+
}
|
|
131
|
+
const route = routes[0];
|
|
132
|
+
if (route.factory.toLowerCase() !== factoryAddr.toLowerCase()) {
|
|
133
|
+
return { delta0: 0n, delta1: 0n };
|
|
134
|
+
}
|
|
135
|
+
const fromLower = route.from.toLowerCase();
|
|
136
|
+
const toLower = route.to.toLowerCase();
|
|
137
|
+
const t0 = token0.toLowerCase();
|
|
138
|
+
const t1 = token1.toLowerCase();
|
|
139
|
+
if (fromLower === t0 && toLower === t1) {
|
|
140
|
+
return { delta0: amountIn, delta1: -amountOut };
|
|
141
|
+
}
|
|
142
|
+
if (fromLower === t1 && toLower === t0) {
|
|
143
|
+
return { delta0: -amountOut, delta1: amountIn };
|
|
144
|
+
}
|
|
145
|
+
return { delta0: 0n, delta1: 0n };
|
|
146
|
+
}
|
|
86
147
|
/**
|
|
87
148
|
* Estimates minimum LP tokens from zap in amounts.
|
|
88
149
|
*
|
|
@@ -2,7 +2,7 @@ import { ROUTER_ABI } from '../../core/abis';
|
|
|
2
2
|
import { getContractAddress } from '../../core/constants';
|
|
3
3
|
import { validateAddress } from '../../utils/validation';
|
|
4
4
|
import { buildApprovalParams, getAllowance, calculateMinAmount, getPoolInfo, getPoolSnapshot } from './liquidityHelpers';
|
|
5
|
-
import { encodeZapInCall, findZapInRoutes, splitAmount, estimateLiquidityFromZapIn, } from './zapHelpers';
|
|
5
|
+
import { encodeZapInCall, findZapInRoutes, splitAmount, estimateLiquidityFromZapIn, quoteAddLiquidityFromReserves, computeTargetPoolImpact, } from './zapHelpers';
|
|
6
6
|
// ========== ZAP IN OPERATIONS ==========
|
|
7
7
|
/**
|
|
8
8
|
* Builds a complete zap in transaction including approval if needed
|
|
@@ -66,8 +66,27 @@ async function prepareZapInContextInternal(publicClient, chainId, poolService, r
|
|
|
66
66
|
functionName: 'generateZapInParams',
|
|
67
67
|
args: [token0, token1, factoryAddr, amountInA, amountInB, routesA, routesB],
|
|
68
68
|
}));
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
// Re-quote amountAMin / amountBMin against POST-swap reserves.
|
|
70
|
+
//
|
|
71
|
+
// `generateZapInParams` calls `quoteAddLiquidity` with the pool's *current*
|
|
72
|
+
// reserves, but on-chain `_quoteZapLiquidity` runs *after* the zap's internal
|
|
73
|
+
// swap, which moves the same pool when tokenIn is one of the pool tokens.
|
|
74
|
+
// Applying user slippage on top of a pre-swap minimum makes the contract
|
|
75
|
+
// reject any non-trivial amount because the deterministic price impact of
|
|
76
|
+
// the swap alone exceeds the slippage budget. Predict the post-swap reserves
|
|
77
|
+
// and re-derive the minimums so that user slippage only covers real drift
|
|
78
|
+
// between quote-time and execution.
|
|
79
|
+
const impactA = computeTargetPoolImpact(routesA, amountInA, amountOutMinA, token0, token1, factoryAddr);
|
|
80
|
+
const impactB = computeTargetPoolImpact(routesB, amountInB, amountOutMinB, token0, token1, factoryAddr);
|
|
81
|
+
const projectedReserveA = poolSnapshot.reserve0 + impactA.delta0 + impactB.delta0;
|
|
82
|
+
const projectedReserveB = poolSnapshot.reserve1 + impactA.delta1 + impactB.delta1;
|
|
83
|
+
const useReserveA = projectedReserveA > 0n ? projectedReserveA : poolSnapshot.reserve0;
|
|
84
|
+
const useReserveB = projectedReserveB > 0n ? projectedReserveB : poolSnapshot.reserve1;
|
|
85
|
+
const projected = quoteAddLiquidityFromReserves(amountOutMinA, amountOutMinB, useReserveA, useReserveB);
|
|
86
|
+
const baselineAmountAMin = projected.amountA > 0n ? projected.amountA : amountAMin;
|
|
87
|
+
const baselineAmountBMin = projected.amountB > 0n ? projected.amountB : amountBMin;
|
|
88
|
+
const finalAmountAMin = calculateMinAmount(baselineAmountAMin, options.slippageTolerance);
|
|
89
|
+
const finalAmountBMin = calculateMinAmount(baselineAmountBMin, options.slippageTolerance);
|
|
71
90
|
const finalAmountOutMinA = calculateMinAmount(amountOutMinA, options.slippageTolerance);
|
|
72
91
|
const finalAmountOutMinB = calculateMinAmount(amountOutMinB, options.slippageTolerance);
|
|
73
92
|
const expectedLiquidity = estimateLiquidityFromZapIn(finalAmountOutMinA, finalAmountOutMinB, poolSnapshot.reserve0, poolSnapshot.reserve1, poolSnapshot.totalSupply);
|
|
@@ -47,6 +47,40 @@ export declare function splitAmount(amountIn: bigint, splitRatio: number): {
|
|
|
47
47
|
amountA: bigint;
|
|
48
48
|
amountB: bigint;
|
|
49
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* Off-chain mirror of Router.sol's quoteAddLiquidity / _quoteZapLiquidity logic.
|
|
52
|
+
*
|
|
53
|
+
* Given desired amounts and pool reserves, returns the (amountA, amountB) the
|
|
54
|
+
* router will actually deposit when adding liquidity. Used to predict the exact
|
|
55
|
+
* `amountAMin` / `amountBMin` the contract will check against post-swap reserves.
|
|
56
|
+
*
|
|
57
|
+
* @param amountADesired - Desired amount of tokenA
|
|
58
|
+
* @param amountBDesired - Desired amount of tokenB
|
|
59
|
+
* @param reserveA - Reserve of tokenA at the moment liquidity is added
|
|
60
|
+
* @param reserveB - Reserve of tokenB at the moment liquidity is added
|
|
61
|
+
*/
|
|
62
|
+
export declare function quoteAddLiquidityFromReserves(amountADesired: bigint, amountBDesired: bigint, reserveA: bigint, reserveB: bigint): {
|
|
63
|
+
amountA: bigint;
|
|
64
|
+
amountB: bigint;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Computes the net delta a single-hop zap swap applies to a target pool's
|
|
68
|
+
* reserves. Returns `{delta0, delta1}` to add to the pool's pre-swap reserves
|
|
69
|
+
* to obtain the reserves the router will see when it runs `_quoteZapLiquidity`.
|
|
70
|
+
*
|
|
71
|
+
* Only single-hop routes whose factory matches the target pool's factory and
|
|
72
|
+
* whose `(from, to)` are `(token0, token1)` (in either direction) are
|
|
73
|
+
* considered. Multi-hop routes and routes through other pools have no effect
|
|
74
|
+
* on the target pool's reserves and return `{0, 0}`.
|
|
75
|
+
*
|
|
76
|
+
* Note: Multi-hop routes that traverse the target pool as an intermediate hop
|
|
77
|
+
* are intentionally not handled here — they are uncommon for single-sided zaps
|
|
78
|
+
* and would require per-hop amounts from `getAmountsOut`.
|
|
79
|
+
*/
|
|
80
|
+
export declare function computeTargetPoolImpact(routes: RouterRoute[], amountIn: bigint, amountOut: bigint, token0: Address, token1: Address, factoryAddr: Address): {
|
|
81
|
+
delta0: bigint;
|
|
82
|
+
delta1: bigint;
|
|
83
|
+
};
|
|
50
84
|
/**
|
|
51
85
|
* Estimates minimum LP tokens from zap in amounts.
|
|
52
86
|
*
|
|
@@ -5,6 +5,8 @@ exports.encodeZapOutCall = encodeZapOutCall;
|
|
|
5
5
|
exports.findZapInRoutes = findZapInRoutes;
|
|
6
6
|
exports.findZapOutRoutes = findZapOutRoutes;
|
|
7
7
|
exports.splitAmount = splitAmount;
|
|
8
|
+
exports.quoteAddLiquidityFromReserves = quoteAddLiquidityFromReserves;
|
|
9
|
+
exports.computeTargetPoolImpact = computeTargetPoolImpact;
|
|
8
10
|
exports.estimateLiquidityFromZapIn = estimateLiquidityFromZapIn;
|
|
9
11
|
const viem_1 = require("viem");
|
|
10
12
|
const abis_1 = require("../../core/abis");
|
|
@@ -91,6 +93,67 @@ function splitAmount(amountIn, splitRatio) {
|
|
|
91
93
|
const amountB = amountIn - amountA;
|
|
92
94
|
return { amountA, amountB };
|
|
93
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Off-chain mirror of Router.sol's quoteAddLiquidity / _quoteZapLiquidity logic.
|
|
98
|
+
*
|
|
99
|
+
* Given desired amounts and pool reserves, returns the (amountA, amountB) the
|
|
100
|
+
* router will actually deposit when adding liquidity. Used to predict the exact
|
|
101
|
+
* `amountAMin` / `amountBMin` the contract will check against post-swap reserves.
|
|
102
|
+
*
|
|
103
|
+
* @param amountADesired - Desired amount of tokenA
|
|
104
|
+
* @param amountBDesired - Desired amount of tokenB
|
|
105
|
+
* @param reserveA - Reserve of tokenA at the moment liquidity is added
|
|
106
|
+
* @param reserveB - Reserve of tokenB at the moment liquidity is added
|
|
107
|
+
*/
|
|
108
|
+
function quoteAddLiquidityFromReserves(amountADesired, amountBDesired, reserveA, reserveB) {
|
|
109
|
+
if (reserveA === 0n && reserveB === 0n) {
|
|
110
|
+
return { amountA: amountADesired, amountB: amountBDesired };
|
|
111
|
+
}
|
|
112
|
+
if (reserveA === 0n || reserveB === 0n) {
|
|
113
|
+
// Mirrors Router.sol's InsufficientLiquidity revert. Caller can fall back.
|
|
114
|
+
return { amountA: 0n, amountB: 0n };
|
|
115
|
+
}
|
|
116
|
+
const amountBOptimal = (amountADesired * reserveB) / reserveA;
|
|
117
|
+
if (amountBOptimal <= amountBDesired) {
|
|
118
|
+
return { amountA: amountADesired, amountB: amountBOptimal };
|
|
119
|
+
}
|
|
120
|
+
const amountAOptimal = (amountBDesired * reserveA) / reserveB;
|
|
121
|
+
return { amountA: amountAOptimal, amountB: amountBDesired };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Computes the net delta a single-hop zap swap applies to a target pool's
|
|
125
|
+
* reserves. Returns `{delta0, delta1}` to add to the pool's pre-swap reserves
|
|
126
|
+
* to obtain the reserves the router will see when it runs `_quoteZapLiquidity`.
|
|
127
|
+
*
|
|
128
|
+
* Only single-hop routes whose factory matches the target pool's factory and
|
|
129
|
+
* whose `(from, to)` are `(token0, token1)` (in either direction) are
|
|
130
|
+
* considered. Multi-hop routes and routes through other pools have no effect
|
|
131
|
+
* on the target pool's reserves and return `{0, 0}`.
|
|
132
|
+
*
|
|
133
|
+
* Note: Multi-hop routes that traverse the target pool as an intermediate hop
|
|
134
|
+
* are intentionally not handled here — they are uncommon for single-sided zaps
|
|
135
|
+
* and would require per-hop amounts from `getAmountsOut`.
|
|
136
|
+
*/
|
|
137
|
+
function computeTargetPoolImpact(routes, amountIn, amountOut, token0, token1, factoryAddr) {
|
|
138
|
+
if (routes.length !== 1) {
|
|
139
|
+
return { delta0: 0n, delta1: 0n };
|
|
140
|
+
}
|
|
141
|
+
const route = routes[0];
|
|
142
|
+
if (route.factory.toLowerCase() !== factoryAddr.toLowerCase()) {
|
|
143
|
+
return { delta0: 0n, delta1: 0n };
|
|
144
|
+
}
|
|
145
|
+
const fromLower = route.from.toLowerCase();
|
|
146
|
+
const toLower = route.to.toLowerCase();
|
|
147
|
+
const t0 = token0.toLowerCase();
|
|
148
|
+
const t1 = token1.toLowerCase();
|
|
149
|
+
if (fromLower === t0 && toLower === t1) {
|
|
150
|
+
return { delta0: amountIn, delta1: -amountOut };
|
|
151
|
+
}
|
|
152
|
+
if (fromLower === t1 && toLower === t0) {
|
|
153
|
+
return { delta0: -amountOut, delta1: amountIn };
|
|
154
|
+
}
|
|
155
|
+
return { delta0: 0n, delta1: 0n };
|
|
156
|
+
}
|
|
94
157
|
/**
|
|
95
158
|
* Estimates minimum LP tokens from zap in amounts.
|
|
96
159
|
*
|
|
@@ -72,8 +72,27 @@ async function prepareZapInContextInternal(publicClient, chainId, poolService, r
|
|
|
72
72
|
functionName: 'generateZapInParams',
|
|
73
73
|
args: [token0, token1, factoryAddr, amountInA, amountInB, routesA, routesB],
|
|
74
74
|
}));
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
// Re-quote amountAMin / amountBMin against POST-swap reserves.
|
|
76
|
+
//
|
|
77
|
+
// `generateZapInParams` calls `quoteAddLiquidity` with the pool's *current*
|
|
78
|
+
// reserves, but on-chain `_quoteZapLiquidity` runs *after* the zap's internal
|
|
79
|
+
// swap, which moves the same pool when tokenIn is one of the pool tokens.
|
|
80
|
+
// Applying user slippage on top of a pre-swap minimum makes the contract
|
|
81
|
+
// reject any non-trivial amount because the deterministic price impact of
|
|
82
|
+
// the swap alone exceeds the slippage budget. Predict the post-swap reserves
|
|
83
|
+
// and re-derive the minimums so that user slippage only covers real drift
|
|
84
|
+
// between quote-time and execution.
|
|
85
|
+
const impactA = (0, zapHelpers_1.computeTargetPoolImpact)(routesA, amountInA, amountOutMinA, token0, token1, factoryAddr);
|
|
86
|
+
const impactB = (0, zapHelpers_1.computeTargetPoolImpact)(routesB, amountInB, amountOutMinB, token0, token1, factoryAddr);
|
|
87
|
+
const projectedReserveA = poolSnapshot.reserve0 + impactA.delta0 + impactB.delta0;
|
|
88
|
+
const projectedReserveB = poolSnapshot.reserve1 + impactA.delta1 + impactB.delta1;
|
|
89
|
+
const useReserveA = projectedReserveA > 0n ? projectedReserveA : poolSnapshot.reserve0;
|
|
90
|
+
const useReserveB = projectedReserveB > 0n ? projectedReserveB : poolSnapshot.reserve1;
|
|
91
|
+
const projected = (0, zapHelpers_1.quoteAddLiquidityFromReserves)(amountOutMinA, amountOutMinB, useReserveA, useReserveB);
|
|
92
|
+
const baselineAmountAMin = projected.amountA > 0n ? projected.amountA : amountAMin;
|
|
93
|
+
const baselineAmountBMin = projected.amountB > 0n ? projected.amountB : amountBMin;
|
|
94
|
+
const finalAmountAMin = (0, liquidityHelpers_1.calculateMinAmount)(baselineAmountAMin, options.slippageTolerance);
|
|
95
|
+
const finalAmountBMin = (0, liquidityHelpers_1.calculateMinAmount)(baselineAmountBMin, options.slippageTolerance);
|
|
77
96
|
const finalAmountOutMinA = (0, liquidityHelpers_1.calculateMinAmount)(amountOutMinA, options.slippageTolerance);
|
|
78
97
|
const finalAmountOutMinB = (0, liquidityHelpers_1.calculateMinAmount)(amountOutMinB, options.slippageTolerance);
|
|
79
98
|
const expectedLiquidity = (0, zapHelpers_1.estimateLiquidityFromZapIn)(finalAmountOutMinA, finalAmountOutMinB, poolSnapshot.reserve0, poolSnapshot.reserve1, poolSnapshot.totalSupply);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mento-protocol/mento-sdk",
|
|
3
3
|
"description": "Official SDK for interacting with the Mento Protocol",
|
|
4
|
-
"version": "3.2.
|
|
4
|
+
"version": "3.2.7-beta.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Mento Labs",
|
|
7
7
|
"keywords": [
|
|
@@ -80,5 +80,11 @@
|
|
|
80
80
|
},
|
|
81
81
|
"dependencies": {
|
|
82
82
|
"viem": "^2.21.44"
|
|
83
|
+
},
|
|
84
|
+
"pnpm": {
|
|
85
|
+
"onlyBuiltDependencies": [
|
|
86
|
+
"esbuild",
|
|
87
|
+
"unrs-resolver"
|
|
88
|
+
]
|
|
83
89
|
}
|
|
84
90
|
}
|