@andrewkimjoseph/celina-sdk 0.2.6 → 0.2.8
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/build/abis/permit2.d.ts +43 -0
- package/build/abis/permit2.js +30 -0
- package/build/abis/permit2.js.map +1 -0
- package/build/abis/uniswap-state-view.d.ts +34 -0
- package/build/abis/uniswap-state-view.js +22 -0
- package/build/abis/uniswap-state-view.js.map +1 -0
- package/build/abis/uniswap-v4-quoter.d.ts +86 -0
- package/build/abis/uniswap-v4-quoter.js +64 -0
- package/build/abis/uniswap-v4-quoter.js.map +1 -0
- package/build/abis/universal-router.d.ts +16 -0
- package/build/abis/universal-router.js +14 -0
- package/build/abis/universal-router.js.map +1 -0
- package/build/clients/uniswap-sdk.d.ts +4 -0
- package/build/clients/uniswap-sdk.js +9 -0
- package/build/clients/uniswap-sdk.js.map +1 -0
- package/build/config/uniswap.d.ts +36 -0
- package/build/config/uniswap.js +67 -0
- package/build/config/uniswap.js.map +1 -0
- package/build/index.d.ts +5 -0
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/services/uniswap-path-router.d.ts +22 -0
- package/build/services/uniswap-path-router.js +155 -0
- package/build/services/uniswap-path-router.js.map +1 -0
- package/build/services/uniswap-pool-discovery.d.ts +21 -0
- package/build/services/uniswap-pool-discovery.js +183 -0
- package/build/services/uniswap-pool-discovery.js.map +1 -0
- package/build/services/uniswap.service.d.ts +81 -0
- package/build/services/uniswap.service.js +342 -0
- package/build/services/uniswap.service.js.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { v4QuoterAbi } from "../abis/uniswap-v4-quoter.js";
|
|
2
|
+
import { normalizeUniswapPoolKey, UNISWAP_V4, } from "../config/uniswap.js";
|
|
3
|
+
import { getUniswapPoolIndex, } from "./uniswap-pool-discovery.js";
|
|
4
|
+
const MAX_HOPS = 2;
|
|
5
|
+
function otherToken(poolKey, currency) {
|
|
6
|
+
const c = currency.toLowerCase();
|
|
7
|
+
if (poolKey.currency0.toLowerCase() === c)
|
|
8
|
+
return poolKey.currency1;
|
|
9
|
+
if (poolKey.currency1.toLowerCase() === c)
|
|
10
|
+
return poolKey.currency0;
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
function buildPathKeys(pools, currencyIn) {
|
|
14
|
+
let current = currencyIn;
|
|
15
|
+
const pathKeys = [];
|
|
16
|
+
for (const poolKey of pools) {
|
|
17
|
+
const out = otherToken(poolKey, current);
|
|
18
|
+
if (!out) {
|
|
19
|
+
throw new Error("Invalid swap path for Uniswap v4 pools.");
|
|
20
|
+
}
|
|
21
|
+
pathKeys.push({
|
|
22
|
+
intermediateCurrency: out,
|
|
23
|
+
fee: poolKey.fee,
|
|
24
|
+
tickSpacing: poolKey.tickSpacing,
|
|
25
|
+
hooks: poolKey.hooks,
|
|
26
|
+
hookData: "0x",
|
|
27
|
+
});
|
|
28
|
+
current = out;
|
|
29
|
+
}
|
|
30
|
+
return pathKeys;
|
|
31
|
+
}
|
|
32
|
+
function enumeratePaths(index, currencyIn, currencyOut) {
|
|
33
|
+
const start = currencyIn.toLowerCase();
|
|
34
|
+
const goal = currencyOut.toLowerCase();
|
|
35
|
+
if (start === goal) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
const results = [];
|
|
39
|
+
const queue = [{ currency: start, pools: [], visited: new Set([start]) }];
|
|
40
|
+
while (queue.length > 0) {
|
|
41
|
+
const node = queue.shift();
|
|
42
|
+
if (node.pools.length >= MAX_HOPS + 1) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const neighbors = index.adjacency.get(node.currency);
|
|
46
|
+
if (!neighbors) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
for (const neighbor of neighbors) {
|
|
50
|
+
if (node.visited.has(neighbor)) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const poolKey = index.edges.find((edge) => {
|
|
54
|
+
const a = edge.tokenA.toLowerCase();
|
|
55
|
+
const b = edge.tokenB.toLowerCase();
|
|
56
|
+
return ((a === node.currency && b === neighbor) ||
|
|
57
|
+
(a === neighbor && b === node.currency));
|
|
58
|
+
})?.poolKey;
|
|
59
|
+
if (!poolKey) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const nextPools = [...node.pools, poolKey];
|
|
63
|
+
if (neighbor === goal) {
|
|
64
|
+
results.push(nextPools);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (nextPools.length <= MAX_HOPS) {
|
|
68
|
+
queue.push({
|
|
69
|
+
currency: neighbor,
|
|
70
|
+
pools: nextPools,
|
|
71
|
+
visited: new Set([...node.visited, neighbor]),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return results;
|
|
77
|
+
}
|
|
78
|
+
async function quotePath(client, currencyIn, pools, amountIn) {
|
|
79
|
+
if (pools.length === 0) {
|
|
80
|
+
return 0n;
|
|
81
|
+
}
|
|
82
|
+
if (pools.length === 1) {
|
|
83
|
+
const poolKey = normalizeUniswapPoolKey(pools[0]);
|
|
84
|
+
const zeroForOne = currencyIn.toLowerCase() === poolKey.currency0.toLowerCase();
|
|
85
|
+
const { result } = await client.simulateContract({
|
|
86
|
+
address: UNISWAP_V4.v4Quoter,
|
|
87
|
+
abi: v4QuoterAbi,
|
|
88
|
+
functionName: "quoteExactInputSingle",
|
|
89
|
+
args: [
|
|
90
|
+
{
|
|
91
|
+
poolKey,
|
|
92
|
+
zeroForOne,
|
|
93
|
+
exactAmount: amountIn,
|
|
94
|
+
hookData: "0x",
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
});
|
|
98
|
+
return result[0];
|
|
99
|
+
}
|
|
100
|
+
const pathKeys = buildPathKeys(pools, currencyIn);
|
|
101
|
+
const { result } = await client.simulateContract({
|
|
102
|
+
address: UNISWAP_V4.v4Quoter,
|
|
103
|
+
abi: v4QuoterAbi,
|
|
104
|
+
functionName: "quoteExactInput",
|
|
105
|
+
args: [
|
|
106
|
+
{
|
|
107
|
+
exactCurrency: currencyIn,
|
|
108
|
+
path: pathKeys,
|
|
109
|
+
exactAmount: amountIn,
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
});
|
|
113
|
+
return result[0];
|
|
114
|
+
}
|
|
115
|
+
export async function findBestUniswapRoute(client, currencyIn, currencyOut, amountIn) {
|
|
116
|
+
const index = await getUniswapPoolIndex(client);
|
|
117
|
+
const candidatePaths = enumeratePaths(index, currencyIn, currencyOut);
|
|
118
|
+
let best = null;
|
|
119
|
+
for (const pools of candidatePaths) {
|
|
120
|
+
try {
|
|
121
|
+
const amountOut = await quotePath(client, currencyIn, pools, amountIn);
|
|
122
|
+
if (amountOut <= 0n) {
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (!best || amountOut > best.amountOut) {
|
|
126
|
+
best = {
|
|
127
|
+
amountOut,
|
|
128
|
+
route: {
|
|
129
|
+
currencyIn,
|
|
130
|
+
currencyOut,
|
|
131
|
+
pools,
|
|
132
|
+
pathKeys: buildPathKeys(pools, currencyIn),
|
|
133
|
+
hops: pools.length,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// skip paths that fail to quote
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (!best) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
route: best.route,
|
|
147
|
+
amountOut: best.amountOut,
|
|
148
|
+
indexSource: index.source,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
export function applySlippage(amountOut, slippagePercent) {
|
|
152
|
+
const bps = BigInt(Math.round(slippagePercent * 100));
|
|
153
|
+
return (amountOut * (10000n - bps)) / 10000n;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=uniswap-path-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uniswap-path-router.js","sourceRoot":"","sources":["../../src/services/uniswap-path-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type PublicClient } from "viem";
|
|
2
|
+
import { type UniswapPoolKey } from "../config/uniswap.js";
|
|
3
|
+
export type UniswapPoolEdge = {
|
|
4
|
+
poolKey: UniswapPoolKey;
|
|
5
|
+
tokenA: `0x${string}`;
|
|
6
|
+
tokenB: `0x${string}`;
|
|
7
|
+
};
|
|
8
|
+
export type UniswapPoolIndex = {
|
|
9
|
+
edges: UniswapPoolEdge[];
|
|
10
|
+
/** currency address (lowercase) → neighbor currencies */
|
|
11
|
+
adjacency: Map<string, Set<string>>;
|
|
12
|
+
source: "subgraph" | "onchain";
|
|
13
|
+
fetchedAt: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function computeUniswapPoolId(poolKey: UniswapPoolKey): `0x${string}`;
|
|
16
|
+
export declare function getUniswapPoolIndex(client: PublicClient, options?: {
|
|
17
|
+
forceRefresh?: boolean;
|
|
18
|
+
}): Promise<UniswapPoolIndex>;
|
|
19
|
+
export declare function findPoolBetween(index: UniswapPoolIndex, tokenA: `0x${string}`, tokenB: `0x${string}`): UniswapPoolKey | null;
|
|
20
|
+
/** Reset cached index (for tests). */
|
|
21
|
+
export declare function resetUniswapPoolIndexCache(): void;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { encodeAbiParameters, keccak256, parseAbiParameters, } from "viem";
|
|
2
|
+
import { stateViewAbi } from "../abis/uniswap-state-view.js";
|
|
3
|
+
import { normalizeUniswapPoolKey, UNISWAP_DEFAULT_TICK_SPACING, UNISWAP_FEE_TIERS, UNISWAP_HUB_CURRENCIES, UNISWAP_POOL_CACHE_TTL_MS, UNISWAP_SUBGRAPH_URL, UNISWAP_V4, } from "../config/uniswap.js";
|
|
4
|
+
let cachedIndex = null;
|
|
5
|
+
export function computeUniswapPoolId(poolKey) {
|
|
6
|
+
const normalized = normalizeUniswapPoolKey(poolKey);
|
|
7
|
+
return keccak256(encodeAbiParameters(parseAbiParameters("address currency0, address currency1, uint24 fee, int24 tickSpacing, address hooks"), [
|
|
8
|
+
normalized.currency0,
|
|
9
|
+
normalized.currency1,
|
|
10
|
+
normalized.fee,
|
|
11
|
+
normalized.tickSpacing,
|
|
12
|
+
normalized.hooks,
|
|
13
|
+
]));
|
|
14
|
+
}
|
|
15
|
+
function addEdge(edges, adjacency, poolKey) {
|
|
16
|
+
const normalized = normalizeUniswapPoolKey(poolKey);
|
|
17
|
+
const a = normalized.currency0.toLowerCase();
|
|
18
|
+
const b = normalized.currency1.toLowerCase();
|
|
19
|
+
if (edges.some((edge) => edge.poolKey === normalized)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
edges.push({
|
|
23
|
+
poolKey: normalized,
|
|
24
|
+
tokenA: normalized.currency0,
|
|
25
|
+
tokenB: normalized.currency1,
|
|
26
|
+
});
|
|
27
|
+
if (!adjacency.has(a))
|
|
28
|
+
adjacency.set(a, new Set());
|
|
29
|
+
if (!adjacency.has(b))
|
|
30
|
+
adjacency.set(b, new Set());
|
|
31
|
+
adjacency.get(a).add(b);
|
|
32
|
+
adjacency.get(b).add(a);
|
|
33
|
+
}
|
|
34
|
+
async function fetchSubgraphPools() {
|
|
35
|
+
try {
|
|
36
|
+
const response = await fetch(UNISWAP_SUBGRAPH_URL, {
|
|
37
|
+
method: "POST",
|
|
38
|
+
headers: { "Content-Type": "application/json" },
|
|
39
|
+
body: JSON.stringify({
|
|
40
|
+
query: `{
|
|
41
|
+
pools(first: 500, orderBy: totalValueLockedUSD, orderDirection: desc) {
|
|
42
|
+
feeTier
|
|
43
|
+
tickSpacing
|
|
44
|
+
hooks
|
|
45
|
+
token0 { id }
|
|
46
|
+
token1 { id }
|
|
47
|
+
}
|
|
48
|
+
}`,
|
|
49
|
+
}),
|
|
50
|
+
});
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const json = (await response.json());
|
|
55
|
+
const pools = json.data?.pools;
|
|
56
|
+
if (!pools?.length) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const edges = [];
|
|
60
|
+
const adjacency = new Map();
|
|
61
|
+
for (const pool of pools) {
|
|
62
|
+
const poolKey = {
|
|
63
|
+
currency0: pool.token0.id,
|
|
64
|
+
currency1: pool.token1.id,
|
|
65
|
+
fee: Number(pool.feeTier),
|
|
66
|
+
tickSpacing: Number(pool.tickSpacing),
|
|
67
|
+
hooks: (pool.hooks || UNISWAP_V4.zeroHooks),
|
|
68
|
+
};
|
|
69
|
+
addEdge(edges, adjacency, poolKey);
|
|
70
|
+
}
|
|
71
|
+
return edges;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function probePoolOnChain(client, currencyA, currencyB, fee, tickSpacing) {
|
|
78
|
+
const poolKey = normalizeUniswapPoolKey({
|
|
79
|
+
currency0: currencyA,
|
|
80
|
+
currency1: currencyB,
|
|
81
|
+
fee,
|
|
82
|
+
tickSpacing,
|
|
83
|
+
hooks: UNISWAP_V4.zeroHooks,
|
|
84
|
+
});
|
|
85
|
+
const poolId = computeUniswapPoolId(poolKey);
|
|
86
|
+
try {
|
|
87
|
+
const [slot0, liquidity] = await Promise.all([
|
|
88
|
+
client.readContract({
|
|
89
|
+
address: UNISWAP_V4.stateView,
|
|
90
|
+
abi: stateViewAbi,
|
|
91
|
+
functionName: "getSlot0",
|
|
92
|
+
args: [poolId],
|
|
93
|
+
}),
|
|
94
|
+
client.readContract({
|
|
95
|
+
address: UNISWAP_V4.stateView,
|
|
96
|
+
abi: stateViewAbi,
|
|
97
|
+
functionName: "getLiquidity",
|
|
98
|
+
args: [poolId],
|
|
99
|
+
}),
|
|
100
|
+
]);
|
|
101
|
+
if (slot0[0] > 0n && liquidity > 0n) {
|
|
102
|
+
return poolKey;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// pool not initialized
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
async function buildOnChainIndex(client) {
|
|
111
|
+
const edges = [];
|
|
112
|
+
const adjacency = new Map();
|
|
113
|
+
const hubs = [...UNISWAP_HUB_CURRENCIES];
|
|
114
|
+
for (let i = 0; i < hubs.length; i++) {
|
|
115
|
+
for (let j = i + 1; j < hubs.length; j++) {
|
|
116
|
+
const [currency0, currency1] = hubs[i].toLowerCase() < hubs[j].toLowerCase()
|
|
117
|
+
? [hubs[i], hubs[j]]
|
|
118
|
+
: [hubs[j], hubs[i]];
|
|
119
|
+
for (const fee of UNISWAP_FEE_TIERS) {
|
|
120
|
+
const tickSpacing = UNISWAP_DEFAULT_TICK_SPACING[fee] ??
|
|
121
|
+
UNISWAP_DEFAULT_TICK_SPACING[3000];
|
|
122
|
+
const poolKey = await probePoolOnChain(client, currency0, currency1, fee, tickSpacing);
|
|
123
|
+
if (poolKey) {
|
|
124
|
+
addEdge(edges, adjacency, poolKey);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
edges,
|
|
131
|
+
adjacency,
|
|
132
|
+
source: "onchain",
|
|
133
|
+
fetchedAt: Date.now(),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
export async function getUniswapPoolIndex(client, options) {
|
|
137
|
+
const now = Date.now();
|
|
138
|
+
if (!options?.forceRefresh &&
|
|
139
|
+
cachedIndex &&
|
|
140
|
+
now - cachedIndex.fetchedAt < UNISWAP_POOL_CACHE_TTL_MS) {
|
|
141
|
+
return cachedIndex;
|
|
142
|
+
}
|
|
143
|
+
const subgraphEdges = await fetchSubgraphPools();
|
|
144
|
+
if (subgraphEdges?.length) {
|
|
145
|
+
const adjacency = new Map();
|
|
146
|
+
for (const edge of subgraphEdges) {
|
|
147
|
+
const a = edge.tokenA.toLowerCase();
|
|
148
|
+
const b = edge.tokenB.toLowerCase();
|
|
149
|
+
if (!adjacency.has(a))
|
|
150
|
+
adjacency.set(a, new Set());
|
|
151
|
+
if (!adjacency.has(b))
|
|
152
|
+
adjacency.set(b, new Set());
|
|
153
|
+
adjacency.get(a).add(b);
|
|
154
|
+
adjacency.get(b).add(a);
|
|
155
|
+
}
|
|
156
|
+
cachedIndex = {
|
|
157
|
+
edges: subgraphEdges,
|
|
158
|
+
adjacency,
|
|
159
|
+
source: "subgraph",
|
|
160
|
+
fetchedAt: now,
|
|
161
|
+
};
|
|
162
|
+
return cachedIndex;
|
|
163
|
+
}
|
|
164
|
+
cachedIndex = await buildOnChainIndex(client);
|
|
165
|
+
return cachedIndex;
|
|
166
|
+
}
|
|
167
|
+
export function findPoolBetween(index, tokenA, tokenB) {
|
|
168
|
+
const a = tokenA.toLowerCase();
|
|
169
|
+
const b = tokenB.toLowerCase();
|
|
170
|
+
for (const edge of index.edges) {
|
|
171
|
+
const e0 = edge.tokenA.toLowerCase();
|
|
172
|
+
const e1 = edge.tokenB.toLowerCase();
|
|
173
|
+
if ((e0 === a && e1 === b) || (e0 === b && e1 === a)) {
|
|
174
|
+
return edge.poolKey;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
/** Reset cached index (for tests). */
|
|
180
|
+
export function resetUniswapPoolIndexCache() {
|
|
181
|
+
cachedIndex = null;
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=uniswap-pool-discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uniswap-pool-discovery.js","sourceRoot":"","sources":["../../src/services/uniswap-pool-discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { CeloClientFactory } from "../clients/celo-client.js";
|
|
2
|
+
import { type SerializedPreparedFlow } from "../types/prepared.js";
|
|
3
|
+
/** Optional parameters for Uniswap v4 swap estimates and prepares. */
|
|
4
|
+
export interface UniswapSwapParams {
|
|
5
|
+
/** Max slippage tolerance in percent (default `0.5`). */
|
|
6
|
+
slippageTolerance?: number;
|
|
7
|
+
/** Swap deadline in minutes from now (default `5`). */
|
|
8
|
+
deadlineMinutes?: number;
|
|
9
|
+
/** Address receiving output tokens (default: `from`). */
|
|
10
|
+
recipient?: `0x${string}`;
|
|
11
|
+
}
|
|
12
|
+
/** Uniswap v4 quotes, gas estimates, and `prepareSwap` flows on Celo mainnet. */
|
|
13
|
+
export declare class UniswapService {
|
|
14
|
+
private readonly clientFactory;
|
|
15
|
+
private readonly tokenService;
|
|
16
|
+
constructor(clientFactory: CeloClientFactory);
|
|
17
|
+
private resolvePair;
|
|
18
|
+
private baseQuoteFields;
|
|
19
|
+
private buildSwapRoute;
|
|
20
|
+
private buildUniversalRouterCalldata;
|
|
21
|
+
private getApprovalSteps;
|
|
22
|
+
private estimateCallGas;
|
|
23
|
+
private estimateSwapGasWithAllowance;
|
|
24
|
+
/**
|
|
25
|
+
* Expected Uniswap v4 output for a token pair — no wallet required.
|
|
26
|
+
* @param tokenIn - Input token symbol or address
|
|
27
|
+
* @param tokenOut - Output token symbol or address
|
|
28
|
+
* @param amount - Human-readable input amount
|
|
29
|
+
*/
|
|
30
|
+
getSwapQuote(tokenIn: string, tokenOut: string, amount: string): Promise<{
|
|
31
|
+
route: {
|
|
32
|
+
pools: import("../config/uniswap.js").UniswapPoolKey[];
|
|
33
|
+
};
|
|
34
|
+
protocol: "uniswap_v4";
|
|
35
|
+
network: "mainnet";
|
|
36
|
+
tokenIn: string;
|
|
37
|
+
tokenOut: string;
|
|
38
|
+
amountIn: string;
|
|
39
|
+
expectedOut: string;
|
|
40
|
+
routeHops: number;
|
|
41
|
+
indexSource: string | undefined;
|
|
42
|
+
}>;
|
|
43
|
+
/**
|
|
44
|
+
* Simulate gas for a Uniswap v4 swap from `from`, including Permit2 approvals when needed.
|
|
45
|
+
* @param from - Sender wallet address
|
|
46
|
+
* @param tokenIn - Input token symbol or address
|
|
47
|
+
* @param tokenOut - Output token symbol or address
|
|
48
|
+
* @param amount - Human-readable input amount
|
|
49
|
+
* @param params - Optional slippage, deadline, and recipient
|
|
50
|
+
*/
|
|
51
|
+
estimateSwap(from: `0x${string}`, tokenIn: string, tokenOut: string, amount: string, params?: UniswapSwapParams): Promise<{
|
|
52
|
+
from: `0x${string}`;
|
|
53
|
+
recipient: `0x${string}`;
|
|
54
|
+
amountOutMin: string;
|
|
55
|
+
approvalStepsNeeded: number;
|
|
56
|
+
approvalGas: string[];
|
|
57
|
+
swapGas: string | undefined;
|
|
58
|
+
swapGasEstimated: boolean;
|
|
59
|
+
slippageTolerance: number;
|
|
60
|
+
deadline: string;
|
|
61
|
+
deadlineMinutes: number;
|
|
62
|
+
protocol: "uniswap_v4";
|
|
63
|
+
network: "mainnet";
|
|
64
|
+
tokenIn: string;
|
|
65
|
+
tokenOut: string;
|
|
66
|
+
amountIn: string;
|
|
67
|
+
expectedOut: string;
|
|
68
|
+
routeHops: number;
|
|
69
|
+
indexSource: string | undefined;
|
|
70
|
+
}>;
|
|
71
|
+
/**
|
|
72
|
+
* Build unsigned Uniswap v4 steps (ERC-20 approve → Permit2 approve → swap when needed).
|
|
73
|
+
* @param from - Sender wallet address
|
|
74
|
+
* @param tokenIn - Input token symbol or address
|
|
75
|
+
* @param tokenOut - Output token symbol or address
|
|
76
|
+
* @param amount - Human-readable input amount
|
|
77
|
+
* @param params - Optional slippage, deadline, and recipient
|
|
78
|
+
* @returns 1–3 step `SerializedPreparedFlow` for sequential wallet signing
|
|
79
|
+
*/
|
|
80
|
+
prepareSwap(from: `0x${string}`, tokenIn: string, tokenOut: string, amount: string, params?: UniswapSwapParams): Promise<SerializedPreparedFlow>;
|
|
81
|
+
}
|