@continuumdao/ctm-mpc-defi 0.2.22 → 0.2.24
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/agent/catalog.cjs +142 -13
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +282 -43
- package/dist/agent/catalog.js +138 -14
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/gmx/SKILL.md +30 -0
- package/dist/agent/skills/hyperliquid/SKILL.md +32 -0
- package/dist/agent/skills/uniswap-v4/SKILL.md +26 -1
- package/dist/core/index.d.ts +4 -36
- package/dist/eip712Multisign-xhXpUYp3.d.ts +36 -0
- package/dist/index.cjs +344 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +344 -12
- package/dist/index.js.map +1 -1
- package/dist/protocols/evm/gmx/index.cjs +39 -0
- package/dist/protocols/evm/gmx/index.cjs.map +1 -1
- package/dist/protocols/evm/gmx/index.d.ts +21 -1
- package/dist/protocols/evm/gmx/index.js +38 -1
- package/dist/protocols/evm/gmx/index.js.map +1 -1
- package/dist/protocols/evm/hyperliquid/index.cjs +478 -208
- package/dist/protocols/evm/hyperliquid/index.cjs.map +1 -1
- package/dist/protocols/evm/hyperliquid/index.d.ts +166 -51
- package/dist/protocols/evm/hyperliquid/index.js +467 -210
- package/dist/protocols/evm/hyperliquid/index.js.map +1 -1
- package/dist/protocols/evm/permit2/index.cjs.map +1 -1
- package/dist/protocols/evm/permit2/index.js.map +1 -1
- package/dist/protocols/evm/uniswap-v4/index.cjs +734 -15
- package/dist/protocols/evm/uniswap-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/uniswap-v4/index.d.ts +189 -17
- package/dist/protocols/evm/uniswap-v4/index.js +698 -16
- package/dist/protocols/evm/uniswap-v4/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -68,8 +68,18 @@ var UNIVERSAL_ROUTER_SPENDER = {
|
|
|
68
68
|
143: "0x0d97dc33264bfc1c226207428a79b26757fb9dc3",
|
|
69
69
|
59144: "0x661e93cca42afacb172121ef892830ca3b70f08d",
|
|
70
70
|
4217: "0x1febb76be10aaf3a1402f04e8e835f2c382f7914",
|
|
71
|
-
196: "0x5507749f2c558bb3e162c6e90c314c092e7372ff"
|
|
71
|
+
196: "0x5507749f2c558bb3e162c6e90c314c092e7372ff",
|
|
72
|
+
/** Robinhood Chain mainnet — Universal Router v2.1.1 (Trade API / interface) */
|
|
73
|
+
4663: "0x8876789976decbfcbbbe364623c63652db8c0904"
|
|
72
74
|
};
|
|
75
|
+
var UNIVERSAL_ROUTER_VERSION_BY_CHAIN = {
|
|
76
|
+
/** Robinhood has UR 2.1.1 only in the supported-chains table (no 2.0 Trade API column). */
|
|
77
|
+
4663: "2.1.1"
|
|
78
|
+
};
|
|
79
|
+
function getUniswapUniversalRouterVersion(chainId) {
|
|
80
|
+
const v = UNIVERSAL_ROUTER_VERSION_BY_CHAIN[chainId];
|
|
81
|
+
return typeof v === "string" && v.trim() ? v.trim() : UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT;
|
|
82
|
+
}
|
|
73
83
|
function isUniswapV4ChainSupported(chainId) {
|
|
74
84
|
if (chainId == null) return false;
|
|
75
85
|
const n = parseEvmChainIdToNumber(chainId);
|
|
@@ -106,8 +116,12 @@ var POSITION_MANAGER_BY_CHAIN = {
|
|
|
106
116
|
11155111: "0x4B2C77d209D3405F41a037Ec6c77F7F5b8e2ca80",
|
|
107
117
|
130: "0x0d97dc33264bfc1c226207428a79b26757fb9dc3",
|
|
108
118
|
1868: "0x0e2850543f69f678257266e0907ff9a58b3f13de",
|
|
109
|
-
59144: "0x661e93cca42afacb172121ef892830ca3b70f08d"
|
|
119
|
+
59144: "0x661e93cca42afacb172121ef892830ca3b70f08d",
|
|
120
|
+
/** Robinhood Chain mainnet */
|
|
121
|
+
4663: "0x58daec3116aae6D93017bAAea7749052E8a04fA7"
|
|
110
122
|
};
|
|
123
|
+
var ROBINHOOD_CHAIN_ID = 4663;
|
|
124
|
+
var ROBINHOOD_WETH_ADDRESS = "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73";
|
|
111
125
|
function getUniswapV4PositionManagerOrThrow(chainId) {
|
|
112
126
|
const raw = POSITION_MANAGER_BY_CHAIN[chainId];
|
|
113
127
|
if (!raw || !raw.startsWith("0x") || raw.length !== 42) {
|
|
@@ -160,8 +174,8 @@ function parseUniswapChainId(value) {
|
|
|
160
174
|
function trimAddr(a) {
|
|
161
175
|
return a.trim();
|
|
162
176
|
}
|
|
163
|
-
function
|
|
164
|
-
const t = (
|
|
177
|
+
function isUniswapNativeTokenAddress(token) {
|
|
178
|
+
const t = (token ?? "").toString().trim();
|
|
165
179
|
if (!t) return false;
|
|
166
180
|
try {
|
|
167
181
|
return viem.getAddress(t) === viem.zeroAddress;
|
|
@@ -169,6 +183,9 @@ function isUniswapTokenInAddressNative(tokenIn) {
|
|
|
169
183
|
return t.toLowerCase() === "0x0000000000000000000000000000000000000000";
|
|
170
184
|
}
|
|
171
185
|
}
|
|
186
|
+
function isUniswapTokenInAddressNative(tokenIn) {
|
|
187
|
+
return isUniswapNativeTokenAddress(tokenIn);
|
|
188
|
+
}
|
|
172
189
|
function isUniswapFullQuoteResponseNativeIn(stored) {
|
|
173
190
|
if (!stored) return false;
|
|
174
191
|
const q = stored.quote;
|
|
@@ -176,7 +193,16 @@ function isUniswapFullQuoteResponseNativeIn(stored) {
|
|
|
176
193
|
const input = q.input;
|
|
177
194
|
if (!input) return false;
|
|
178
195
|
const raw = (input.address ?? input.token ?? "").toString().trim();
|
|
179
|
-
return
|
|
196
|
+
return isUniswapNativeTokenAddress(raw);
|
|
197
|
+
}
|
|
198
|
+
function isUniswapFullQuoteResponseNativeOut(stored) {
|
|
199
|
+
if (!stored) return false;
|
|
200
|
+
const q = stored.quote;
|
|
201
|
+
if (!q || typeof q !== "object" || Array.isArray(q)) return false;
|
|
202
|
+
const output = q.output;
|
|
203
|
+
if (!output) return false;
|
|
204
|
+
const raw = (output.address ?? output.token ?? "").toString().trim();
|
|
205
|
+
return isUniswapNativeTokenAddress(raw);
|
|
180
206
|
}
|
|
181
207
|
async function fetchEthereumAddressForKeyGen(managementNodeUrl, keyGenId, readAuth = { bearerOnGet: true, jwt: null }, init) {
|
|
182
208
|
const base = managementNodeUrl.trim().replace(/\/$/, "");
|
|
@@ -238,6 +264,31 @@ function buildUniswapQuoteRequestBody(args) {
|
|
|
238
264
|
}
|
|
239
265
|
return body;
|
|
240
266
|
}
|
|
267
|
+
function resolveChainIdFromStoredUniswapQuote(stored) {
|
|
268
|
+
if (!stored) return 0;
|
|
269
|
+
const top = stored;
|
|
270
|
+
for (const key of ["tokenInChainId", "chainId"]) {
|
|
271
|
+
const raw = top[key];
|
|
272
|
+
if (raw != null && String(raw).trim() !== "") {
|
|
273
|
+
try {
|
|
274
|
+
return parseUniswapChainId(raw);
|
|
275
|
+
} catch {
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
const q = top.quote;
|
|
280
|
+
if (q && typeof q === "object" && !Array.isArray(q)) {
|
|
281
|
+
const input = q.input;
|
|
282
|
+
const chain = input?.chainId;
|
|
283
|
+
if (chain != null && String(chain).trim() !== "") {
|
|
284
|
+
try {
|
|
285
|
+
return parseUniswapChainId(chain);
|
|
286
|
+
} catch {
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return 0;
|
|
291
|
+
}
|
|
241
292
|
function errorMessageFromUniswapJsonBody(value) {
|
|
242
293
|
if (value == null) return null;
|
|
243
294
|
if (typeof value === "string") {
|
|
@@ -350,16 +401,18 @@ async function uniswapTradeQuote(args) {
|
|
|
350
401
|
}
|
|
351
402
|
const base = args.baseUrl && args.baseUrl.trim() ? args.baseUrl.trim().replace(/\/$/, "") : DEFAULT_TRADE_BASE;
|
|
352
403
|
const quoteUrl = `${base}/quote`;
|
|
353
|
-
const
|
|
404
|
+
const chainIdForRouter = parseUniswapChainId(resolveInputChainId(args));
|
|
405
|
+
const urv = args.universalRouterVersion && args.universalRouterVersion.trim() || getUniswapUniversalRouterVersion(chainIdForRouter);
|
|
354
406
|
const body = buildUniswapQuoteRequestBody({ ...args, swapper });
|
|
355
|
-
const nativeIn =
|
|
407
|
+
const nativeIn = isUniswapNativeTokenAddress(args.tokenIn);
|
|
408
|
+
const nativeOut = isUniswapNativeTokenAddress(args.tokenOut);
|
|
356
409
|
const headers = {
|
|
357
410
|
...UNISWAP_QUOTE_HEADERS_BASE,
|
|
358
411
|
"x-api-key": apiKey,
|
|
359
412
|
"x-universal-router-version": urv,
|
|
360
413
|
"x-permit2-disabled": args.permit2Disabled === true ? "true" : "false",
|
|
361
|
-
/** Native (0x0)
|
|
362
|
-
"x-erc20eth-enabled": nativeIn ? "true" : "false"
|
|
414
|
+
/** Native (0x0) in or out: enables ERC20↔ETH routes (incl. UniswapX on Robinhood). */
|
|
415
|
+
"x-erc20eth-enabled": nativeIn || nativeOut ? "true" : "false"
|
|
363
416
|
};
|
|
364
417
|
const fetchFn = args.fetchImpl ?? globalThis.fetch;
|
|
365
418
|
const res = await fetchFn(quoteUrl, {
|
|
@@ -370,7 +423,11 @@ async function uniswapTradeQuote(args) {
|
|
|
370
423
|
});
|
|
371
424
|
const text = await res.text();
|
|
372
425
|
if (!res.ok) {
|
|
373
|
-
|
|
426
|
+
let msg = messageFromUniswapHttpResponseBody(text, res.status, res.statusText);
|
|
427
|
+
if (res.status === 404 && chainIdForRouter === 4663) {
|
|
428
|
+
msg += " On Robinhood Chain, confirm USDG is 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168, use Native ETH or WETH (0x0Bd7\u2026) as output, and try at least ~$300 notional (UniswapX minimum).";
|
|
429
|
+
}
|
|
430
|
+
throw new Error(msg);
|
|
374
431
|
}
|
|
375
432
|
const forParse = text.replace(/^\uFEFF/, "");
|
|
376
433
|
try {
|
|
@@ -934,16 +991,17 @@ async function uniswapCreateSwap(args) {
|
|
|
934
991
|
quote: classic,
|
|
935
992
|
deadline
|
|
936
993
|
};
|
|
937
|
-
const urv = (args.universalRouterVersion ??
|
|
994
|
+
const urv = (args.universalRouterVersion ?? "").trim() || getUniswapUniversalRouterVersion(resolveChainIdFromStoredUniswapQuote(args.fullQuoteFromPermit));
|
|
938
995
|
const fn = args.fetchImpl ?? globalThis.fetch;
|
|
939
996
|
const nativeIn = isUniswapFullQuoteResponseNativeIn(args.fullQuoteFromPermit);
|
|
997
|
+
const nativeOut = isUniswapFullQuoteResponseNativeOut(args.fullQuoteFromPermit);
|
|
940
998
|
const res = await fn(url, {
|
|
941
999
|
method: "POST",
|
|
942
1000
|
headers: {
|
|
943
1001
|
"Content-Type": "application/json",
|
|
944
1002
|
"x-api-key": args.uniswapApiKey.trim(),
|
|
945
1003
|
"x-universal-router-version": urv,
|
|
946
|
-
"x-erc20eth-enabled": nativeIn ? "true" : "false",
|
|
1004
|
+
"x-erc20eth-enabled": nativeIn || nativeOut ? "true" : "false",
|
|
947
1005
|
"x-permit2-disabled": "true"
|
|
948
1006
|
},
|
|
949
1007
|
body: JSON.stringify(body)
|
|
@@ -2657,6 +2715,11 @@ function uniswapV4SubgraphIdForChain(chainId) {
|
|
|
2657
2715
|
function uniswapV4SubgraphSupportedChainIds() {
|
|
2658
2716
|
return Object.keys(UNISWAP_V4_SUBGRAPH_ID_BY_CHAIN_ID).map(Number).sort((a, b) => a - b);
|
|
2659
2717
|
}
|
|
2718
|
+
function uniswapV4OhlcvSupportedChainIds() {
|
|
2719
|
+
const ids = new Set(uniswapV4SubgraphSupportedChainIds());
|
|
2720
|
+
ids.add(4663);
|
|
2721
|
+
return [...ids].sort((a, b) => a - b);
|
|
2722
|
+
}
|
|
2660
2723
|
function uniswapV4SubgraphUrlForChain(chainId, apiKey) {
|
|
2661
2724
|
const id = uniswapV4SubgraphIdForChain(chainId);
|
|
2662
2725
|
if (!id) {
|
|
@@ -2828,6 +2891,44 @@ async function fetchUniswapV4PoolMeta(args) {
|
|
|
2828
2891
|
return data.pool ?? null;
|
|
2829
2892
|
}
|
|
2830
2893
|
|
|
2894
|
+
// src/protocols/evm/uniswap-v4/bitqueryApiKey.ts
|
|
2895
|
+
var BITQUERY_API_KEY_ENV = "BITQUERY_API_KEY";
|
|
2896
|
+
var BITQUERY_API_KEY_SIGNUP_URL = "https://account.bitquery.io/";
|
|
2897
|
+
var BITQUERY_API_KEY_DOCS_URL = "https://bitquery.io/blockchains/robinhood-chain-api";
|
|
2898
|
+
var BITQUERY_GRAPHQL_URL = "https://graphql.bitquery.io";
|
|
2899
|
+
function resolveBitqueryApiKey(override) {
|
|
2900
|
+
const fromOverride = override?.trim();
|
|
2901
|
+
if (fromOverride) return fromOverride;
|
|
2902
|
+
const raw = process.env[BITQUERY_API_KEY_ENV]?.trim();
|
|
2903
|
+
return raw || void 0;
|
|
2904
|
+
}
|
|
2905
|
+
function isBitqueryAuthOrRateLimitError(message) {
|
|
2906
|
+
const m = message.toLowerCase();
|
|
2907
|
+
const mentionsBitquery = m.includes("bitquery") || m.includes("bitquery_api_key") || m.includes("robinhood chain ohlcv");
|
|
2908
|
+
if (!mentionsBitquery) return false;
|
|
2909
|
+
return m.includes("429") || m.includes("rate limit") || m.includes("too many requests") || m.includes("auth") || m.includes("unauthorized") || m.includes("forbidden") || m.includes("api key") || m.includes("access token") || m.includes("required");
|
|
2910
|
+
}
|
|
2911
|
+
function bitqueryApiKeyVariablesHint() {
|
|
2912
|
+
return [
|
|
2913
|
+
`Set \`${BITQUERY_API_KEY_ENV}\` in Node \u2192 AI Agent \u2192 Variables (+ Add: paste the key as the value).`,
|
|
2914
|
+
`Get an API key at ${BITQUERY_API_KEY_SIGNUP_URL}`
|
|
2915
|
+
].join(" ");
|
|
2916
|
+
}
|
|
2917
|
+
function bitqueryAuthErrorMessage(baseError) {
|
|
2918
|
+
return `${baseError}
|
|
2919
|
+
|
|
2920
|
+
Bitquery auth or rate limit \u2014 ${bitqueryApiKeyVariablesHint()}`;
|
|
2921
|
+
}
|
|
2922
|
+
function requireBitqueryApiKey(override) {
|
|
2923
|
+
const key = resolveBitqueryApiKey(override);
|
|
2924
|
+
if (!key) {
|
|
2925
|
+
throw new Error(
|
|
2926
|
+
`Bitquery API key is required for Robinhood Chain OHLCV. ${bitqueryApiKeyVariablesHint()}`
|
|
2927
|
+
);
|
|
2928
|
+
}
|
|
2929
|
+
return key;
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2831
2932
|
// src/protocols/evm/uniswap-v4/ohlcvInterval.ts
|
|
2832
2933
|
var UNISWAP_V4_OHLCV_INTERVALS = [
|
|
2833
2934
|
"1m",
|
|
@@ -2898,6 +2999,179 @@ function resolveUniswapV4OhlcvDataTier(intervalRaw) {
|
|
|
2898
2999
|
);
|
|
2899
3000
|
}
|
|
2900
3001
|
|
|
3002
|
+
// src/protocols/evm/uniswap-v4/bitqueryOhlcv.ts
|
|
3003
|
+
function intervalToBitquerySpec(interval) {
|
|
3004
|
+
const bucketSec = uniswapV4OhlcvIntervalToBucketSec(interval);
|
|
3005
|
+
if (bucketSec < 3600) {
|
|
3006
|
+
return { count: Math.max(1, Math.floor(bucketSec / 60)), in: "minutes" };
|
|
3007
|
+
}
|
|
3008
|
+
if (bucketSec < 86400) {
|
|
3009
|
+
return { count: Math.max(1, Math.floor(bucketSec / 3600)), in: "hours" };
|
|
3010
|
+
}
|
|
3011
|
+
return { count: Math.max(1, Math.floor(bucketSec / 86400)), in: "days" };
|
|
3012
|
+
}
|
|
3013
|
+
function parseIsoOrUnixToMs(raw) {
|
|
3014
|
+
if (raw == null) return null;
|
|
3015
|
+
if (typeof raw === "number" && Number.isFinite(raw)) {
|
|
3016
|
+
return raw > 1e12 ? raw : raw * 1e3;
|
|
3017
|
+
}
|
|
3018
|
+
const s = String(raw).trim();
|
|
3019
|
+
if (!s) return null;
|
|
3020
|
+
if (/^\d+$/.test(s)) {
|
|
3021
|
+
const n = Number(s);
|
|
3022
|
+
return n > 1e12 ? n : n * 1e3;
|
|
3023
|
+
}
|
|
3024
|
+
const ms = Date.parse(s);
|
|
3025
|
+
return Number.isFinite(ms) ? ms : null;
|
|
3026
|
+
}
|
|
3027
|
+
function numToString(raw) {
|
|
3028
|
+
if (raw == null) return null;
|
|
3029
|
+
const n = typeof raw === "number" ? raw : Number(String(raw).trim());
|
|
3030
|
+
if (!Number.isFinite(n)) return null;
|
|
3031
|
+
return String(n);
|
|
3032
|
+
}
|
|
3033
|
+
function mapBitqueryOhlcvRowsToCandles(rows) {
|
|
3034
|
+
const out = [];
|
|
3035
|
+
for (const row of rows) {
|
|
3036
|
+
const timestampMs = parseIsoOrUnixToMs(row.Block?.Time);
|
|
3037
|
+
if (timestampMs == null) continue;
|
|
3038
|
+
const open = numToString(row.Trade?.open);
|
|
3039
|
+
const high = numToString(row.Trade?.high);
|
|
3040
|
+
const low = numToString(row.Trade?.low);
|
|
3041
|
+
const close = numToString(row.Trade?.close);
|
|
3042
|
+
if (open == null || high == null || low == null || close == null) continue;
|
|
3043
|
+
const volume = numToString(row.volumeUsd) ?? numToString(row.volume) ?? void 0;
|
|
3044
|
+
out.push({
|
|
3045
|
+
timestampMs,
|
|
3046
|
+
open,
|
|
3047
|
+
high,
|
|
3048
|
+
low,
|
|
3049
|
+
close,
|
|
3050
|
+
...volume != null ? { volume } : {}
|
|
3051
|
+
});
|
|
3052
|
+
}
|
|
3053
|
+
return out.sort((a, b) => a.timestampMs - b.timestampMs);
|
|
3054
|
+
}
|
|
3055
|
+
function buildCurrencyWhere(filter) {
|
|
3056
|
+
if (filter.kind === "symbol") {
|
|
3057
|
+
const symbol = filter.symbol.trim().replace(/"/g, "");
|
|
3058
|
+
return `Currency: { Symbol: { is: "${symbol}" } }`;
|
|
3059
|
+
}
|
|
3060
|
+
const address = viem.getAddress(filter.address).toLowerCase();
|
|
3061
|
+
return `Currency: { SmartContract: { is: "${address}" } }`;
|
|
3062
|
+
}
|
|
3063
|
+
function buildBitqueryOhlcvQuery(args) {
|
|
3064
|
+
const spec = intervalToBitquerySpec(args.interval);
|
|
3065
|
+
const currencyWhere = buildCurrencyWhere(args.filter);
|
|
3066
|
+
return `query RobinhoodUniswapOhlcv {
|
|
3067
|
+
EVM(network: robinhood) {
|
|
3068
|
+
DEXTradeByTokens(
|
|
3069
|
+
limit: { count: ${args.limit} }
|
|
3070
|
+
orderBy: { ascendingByField: "Block_Time" }
|
|
3071
|
+
where: {
|
|
3072
|
+
TransactionStatus: { Success: true }
|
|
3073
|
+
Trade: {
|
|
3074
|
+
Dex: { ProtocolName: { is: "uniswap_v4" } }
|
|
3075
|
+
${currencyWhere}
|
|
3076
|
+
}
|
|
3077
|
+
Block: { Time: { since: "${args.sinceIso}", till: "${args.tillIso}" } }
|
|
3078
|
+
}
|
|
3079
|
+
) {
|
|
3080
|
+
Block { Time(interval: { count: ${spec.count}, in: ${spec.in} }) }
|
|
3081
|
+
Trade {
|
|
3082
|
+
open: PriceInUSD(minimum: Block_Number)
|
|
3083
|
+
high: PriceInUSD(maximum: Trade_PriceInUSD)
|
|
3084
|
+
low: PriceInUSD(minimum: Trade_PriceInUSD)
|
|
3085
|
+
close: PriceInUSD(maximum: Block_Number)
|
|
3086
|
+
}
|
|
3087
|
+
volumeUsd: sum(of: Trade_Side_AmountInUSD)
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
3090
|
+
}`;
|
|
3091
|
+
}
|
|
3092
|
+
function isRobinhoodOhlcvChain(chainId) {
|
|
3093
|
+
return chainId === ROBINHOOD_CHAIN_ID;
|
|
3094
|
+
}
|
|
3095
|
+
function resolveRobinhoodChartCurrency(args) {
|
|
3096
|
+
const symbol = args.currencySymbol?.trim();
|
|
3097
|
+
if (symbol) return { kind: "symbol", symbol };
|
|
3098
|
+
const direct = args.currencyAddress?.trim();
|
|
3099
|
+
if (direct && direct.startsWith("0x")) {
|
|
3100
|
+
return { kind: "address", address: viem.getAddress(direct) };
|
|
3101
|
+
}
|
|
3102
|
+
const weth = ROBINHOOD_WETH_ADDRESS.toLowerCase();
|
|
3103
|
+
const zero = viem.zeroAddress.toLowerCase();
|
|
3104
|
+
const candidates = [args.tokenOut, args.tokenIn].map((a) => a?.trim()).filter((a) => Boolean(a && a.startsWith("0x"))).map((a) => viem.getAddress(a));
|
|
3105
|
+
const nonWeth = candidates.find((a) => {
|
|
3106
|
+
const lower = a.toLowerCase();
|
|
3107
|
+
return lower !== weth && lower !== zero;
|
|
3108
|
+
});
|
|
3109
|
+
if (nonWeth) return { kind: "address", address: nonWeth };
|
|
3110
|
+
if (candidates[0]) return { kind: "address", address: candidates[0] };
|
|
3111
|
+
throw new Error(
|
|
3112
|
+
"Robinhood OHLCV requires currencyAddress, currencySymbol, or tokenIn/tokenOut (existingPool)."
|
|
3113
|
+
);
|
|
3114
|
+
}
|
|
3115
|
+
function currencyFilterLabel(filter) {
|
|
3116
|
+
if (filter.kind === "symbol") return filter.symbol.toUpperCase();
|
|
3117
|
+
return `${filter.address.slice(0, 6)}\u2026${filter.address.slice(-4)}`;
|
|
3118
|
+
}
|
|
3119
|
+
async function fetchRobinhoodBitqueryOhlcv(args) {
|
|
3120
|
+
const interval = assertUniswapV4OhlcvInterval(args.interval);
|
|
3121
|
+
const apiKey = requireBitqueryApiKey(args.apiKey);
|
|
3122
|
+
const limit = Math.max(1, Math.min(1e3, Math.floor(args.limit ?? 500)));
|
|
3123
|
+
const sinceIso = new Date(args.startTimeMs).toISOString();
|
|
3124
|
+
const tillIso = new Date(args.endTimeMs).toISOString();
|
|
3125
|
+
const query = buildBitqueryOhlcvQuery({
|
|
3126
|
+
filter: args.filter,
|
|
3127
|
+
interval,
|
|
3128
|
+
sinceIso,
|
|
3129
|
+
tillIso,
|
|
3130
|
+
limit
|
|
3131
|
+
});
|
|
3132
|
+
let json;
|
|
3133
|
+
try {
|
|
3134
|
+
const res = await fetch(BITQUERY_GRAPHQL_URL, {
|
|
3135
|
+
method: "POST",
|
|
3136
|
+
headers: {
|
|
3137
|
+
"content-type": "application/json",
|
|
3138
|
+
Authorization: `Bearer ${apiKey}`
|
|
3139
|
+
},
|
|
3140
|
+
body: JSON.stringify({ query })
|
|
3141
|
+
});
|
|
3142
|
+
const text = await res.text();
|
|
3143
|
+
if (!res.ok) {
|
|
3144
|
+
const msg = text ? `Bitquery HTTP ${res.status}: ${text.slice(0, 300)}` : `Bitquery HTTP ${res.status}`;
|
|
3145
|
+
throw new Error(
|
|
3146
|
+
isBitqueryAuthOrRateLimitError(msg) ? bitqueryAuthErrorMessage(msg) : msg
|
|
3147
|
+
);
|
|
3148
|
+
}
|
|
3149
|
+
json = JSON.parse(text);
|
|
3150
|
+
} catch (e) {
|
|
3151
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
3152
|
+
if (isBitqueryAuthOrRateLimitError(msg) && !msg.includes(BITQUERY_GRAPHQL_URL)) {
|
|
3153
|
+
throw new Error(bitqueryAuthErrorMessage(msg));
|
|
3154
|
+
}
|
|
3155
|
+
throw e instanceof Error ? e : new Error(msg);
|
|
3156
|
+
}
|
|
3157
|
+
if (json.errors?.length) {
|
|
3158
|
+
const msg = json.errors.map((e) => e.message ?? "GraphQL error").join("; ");
|
|
3159
|
+
throw new Error(
|
|
3160
|
+
isBitqueryAuthOrRateLimitError(msg) ? bitqueryAuthErrorMessage(msg) : `Bitquery GraphQL: ${msg}`
|
|
3161
|
+
);
|
|
3162
|
+
}
|
|
3163
|
+
const rows = json.data?.EVM?.DEXTradeByTokens ?? [];
|
|
3164
|
+
const candles = mapBitqueryOhlcvRowsToCandles(rows);
|
|
3165
|
+
const warnings = [];
|
|
3166
|
+
if (candles.length === 0) {
|
|
3167
|
+
warnings.push("No Bitquery Uniswap v4 candles for this token and window on Robinhood Chain.");
|
|
3168
|
+
}
|
|
3169
|
+
if (rows.length >= limit) {
|
|
3170
|
+
warnings.push("Bitquery row limit reached; history may be truncated. Shorten lookback or coarsen interval.");
|
|
3171
|
+
}
|
|
3172
|
+
return { candles, warnings };
|
|
3173
|
+
}
|
|
3174
|
+
|
|
2901
3175
|
// src/protocols/evm/uniswap-v4/swapCandles.ts
|
|
2902
3176
|
function parseDecimal(raw) {
|
|
2903
3177
|
if (raw == null) return null;
|
|
@@ -3173,11 +3447,40 @@ async function fetchFromSwapsTier(args) {
|
|
|
3173
3447
|
async function uniswapV4FetchOhlcv(args) {
|
|
3174
3448
|
const chainId = parseUniswapChainId(args.chainId);
|
|
3175
3449
|
const interval = assertUniswapV4OhlcvInterval(args.interval ?? "1h");
|
|
3176
|
-
const tier = resolveUniswapV4OhlcvDataTier(interval);
|
|
3177
|
-
const pool = await resolveUniswapV4OhlcvPool(args);
|
|
3178
3450
|
const { startTimeMs, endTimeMs } = windowFromArgs(args);
|
|
3179
3451
|
const fromSec = Math.floor(startTimeMs / 1e3);
|
|
3180
3452
|
const toSec = Math.ceil(endTimeMs / 1e3);
|
|
3453
|
+
if (isRobinhoodOhlcvChain(chainId)) {
|
|
3454
|
+
const filter = resolveRobinhoodChartCurrency({
|
|
3455
|
+
currencyAddress: args.currencyAddress,
|
|
3456
|
+
currencySymbol: args.currencySymbol,
|
|
3457
|
+
tokenIn: args.existingPool?.token0Address,
|
|
3458
|
+
tokenOut: args.existingPool?.token1Address
|
|
3459
|
+
});
|
|
3460
|
+
const { candles: candles2, warnings: warnings2 } = await fetchRobinhoodBitqueryOhlcv({
|
|
3461
|
+
filter,
|
|
3462
|
+
interval,
|
|
3463
|
+
startTimeMs,
|
|
3464
|
+
endTimeMs
|
|
3465
|
+
});
|
|
3466
|
+
const label = currencyFilterLabel(filter);
|
|
3467
|
+
const window2 = candleWindowFromRows(candles2);
|
|
3468
|
+
return {
|
|
3469
|
+
symbol: label,
|
|
3470
|
+
timeframe: interval,
|
|
3471
|
+
chainId,
|
|
3472
|
+
poolReference: filter.kind === "address" ? filter.address.toLowerCase() : `symbol:${filter.symbol}`,
|
|
3473
|
+
dataSource: "bitquery",
|
|
3474
|
+
priceQuote: "token0PerToken1",
|
|
3475
|
+
...window2,
|
|
3476
|
+
candleCount: candles2.length,
|
|
3477
|
+
candles: candles2,
|
|
3478
|
+
fetchedAtMs: Date.now(),
|
|
3479
|
+
...warnings2.length > 0 ? { warnings: warnings2 } : {}
|
|
3480
|
+
};
|
|
3481
|
+
}
|
|
3482
|
+
const tier = resolveUniswapV4OhlcvDataTier(interval);
|
|
3483
|
+
const pool = await resolveUniswapV4OhlcvPool(args);
|
|
3181
3484
|
const expectedBars = Math.ceil((toSec - fromSec) / tier.bucketSec);
|
|
3182
3485
|
if (expectedBars > MAX_CANDLES) {
|
|
3183
3486
|
throw new Error(
|
|
@@ -3238,6 +3541,370 @@ async function uniswapV4FetchOhlcv(args) {
|
|
|
3238
3541
|
};
|
|
3239
3542
|
}
|
|
3240
3543
|
|
|
3544
|
+
// src/protocols/evm/uniswap-v4/limitOrder.ts
|
|
3545
|
+
function trimAddr3(a) {
|
|
3546
|
+
return a.trim();
|
|
3547
|
+
}
|
|
3548
|
+
var UNISWAP_LIMIT_ORDER_CHAIN_ID = 1;
|
|
3549
|
+
var DEFAULT_UNISWAPX_ORDER_BASE = "https://api.uniswap.org/v2";
|
|
3550
|
+
var DEFAULT_LIMIT_ORDER_QUOTE_PATH = "/limit_order_quote";
|
|
3551
|
+
var DEFAULT_ORDER_SUBMIT_PATH = "/order";
|
|
3552
|
+
var UNISWAP_QUOTE_HEADERS_BASE2 = {
|
|
3553
|
+
"Content-Type": "application/json",
|
|
3554
|
+
"User-Agent": "ctm-mpc-defi uniswapLimitOrderQuote/1.0 (TS)"
|
|
3555
|
+
};
|
|
3556
|
+
function isUniswapLimitOrderChainSupported(chainId) {
|
|
3557
|
+
return parseUniswapChainId(chainId) === UNISWAP_LIMIT_ORDER_CHAIN_ID;
|
|
3558
|
+
}
|
|
3559
|
+
function assertUniswapLimitOrderChain(chainId) {
|
|
3560
|
+
if (!isUniswapLimitOrderChainSupported(chainId)) {
|
|
3561
|
+
throw new Error(
|
|
3562
|
+
`UniswapX limit orders are only supported on Ethereum mainnet (chainId ${UNISWAP_LIMIT_ORDER_CHAIN_ID}). Got ${chainId}. Use market swap on this chain or wait for UniswapX limit support.`
|
|
3563
|
+
);
|
|
3564
|
+
}
|
|
3565
|
+
}
|
|
3566
|
+
function inferPrimaryTypeFromPermitTypes(types) {
|
|
3567
|
+
for (const key of Object.keys(types)) {
|
|
3568
|
+
if (key !== "EIP712Domain") {
|
|
3569
|
+
return key;
|
|
3570
|
+
}
|
|
3571
|
+
}
|
|
3572
|
+
throw new Error("permitData.types missing primaryType (no non-EIP712Domain entry)");
|
|
3573
|
+
}
|
|
3574
|
+
function permitDataToEip712Payload(permitData) {
|
|
3575
|
+
const domain = permitData.domain;
|
|
3576
|
+
const types = permitData.types;
|
|
3577
|
+
const message = permitData.values ?? permitData.message;
|
|
3578
|
+
if (domain == null || typeof domain !== "object" || Array.isArray(domain)) {
|
|
3579
|
+
throw new Error("limit order quote: permitData.domain missing");
|
|
3580
|
+
}
|
|
3581
|
+
if (types == null || typeof types !== "object" || Array.isArray(types)) {
|
|
3582
|
+
throw new Error("limit order quote: permitData.types missing");
|
|
3583
|
+
}
|
|
3584
|
+
if (message == null || typeof message !== "object" || Array.isArray(message)) {
|
|
3585
|
+
throw new Error("limit order quote: permitData.values (message) missing");
|
|
3586
|
+
}
|
|
3587
|
+
const primaryType = typeof permitData.primaryType === "string" && permitData.primaryType.trim() ? permitData.primaryType.trim() : inferPrimaryTypeFromPermitTypes(
|
|
3588
|
+
types
|
|
3589
|
+
);
|
|
3590
|
+
return {
|
|
3591
|
+
domain,
|
|
3592
|
+
types,
|
|
3593
|
+
primaryType,
|
|
3594
|
+
message
|
|
3595
|
+
};
|
|
3596
|
+
}
|
|
3597
|
+
function extractPermitDataFromLimitQuote(quoteResponse) {
|
|
3598
|
+
const permitData = quoteResponse.permitData;
|
|
3599
|
+
if (permitData == null) return null;
|
|
3600
|
+
if (typeof permitData !== "object" || Array.isArray(permitData)) {
|
|
3601
|
+
throw new Error("limit order quote: permitData is not an object");
|
|
3602
|
+
}
|
|
3603
|
+
return permitData;
|
|
3604
|
+
}
|
|
3605
|
+
function buildLimitOrderQuoteRequestBody(args) {
|
|
3606
|
+
const base = buildUniswapQuoteRequestBody({
|
|
3607
|
+
type: args.type,
|
|
3608
|
+
amount: args.amount,
|
|
3609
|
+
tokenIn: args.tokenIn,
|
|
3610
|
+
tokenOut: args.tokenOut,
|
|
3611
|
+
chainId: args.chainId,
|
|
3612
|
+
tokenInChainId: args.tokenInChainId,
|
|
3613
|
+
tokenOutChainId: args.tokenOutChainId,
|
|
3614
|
+
swapper: args.swapper
|
|
3615
|
+
});
|
|
3616
|
+
assertUniswapLimitOrderChain(base.tokenInChainId);
|
|
3617
|
+
return {
|
|
3618
|
+
...base,
|
|
3619
|
+
limitPrice: String(args.limitPrice).trim(),
|
|
3620
|
+
orderDeadline: args.orderDeadline
|
|
3621
|
+
};
|
|
3622
|
+
}
|
|
3623
|
+
async function uniswapLimitOrderQuote(args) {
|
|
3624
|
+
const apiKey = (args.uniswapApiKey || "").trim();
|
|
3625
|
+
if (!apiKey) {
|
|
3626
|
+
throw new Error("uniswapApiKey (x-api-key) is required");
|
|
3627
|
+
}
|
|
3628
|
+
let swapper;
|
|
3629
|
+
if ((args.swapper || "").trim()) {
|
|
3630
|
+
swapper = trimAddr3(args.swapper);
|
|
3631
|
+
} else {
|
|
3632
|
+
const keyGen = (args.keyGen || "").trim();
|
|
3633
|
+
if (!keyGen) {
|
|
3634
|
+
throw new Error("keyGen is required when swapper is not provided");
|
|
3635
|
+
}
|
|
3636
|
+
const mpc = (args.managementNodeUrl || "").trim();
|
|
3637
|
+
if (!mpc) {
|
|
3638
|
+
throw new Error("managementNodeUrl is required when swapper is not provided (to resolve keyGen)");
|
|
3639
|
+
}
|
|
3640
|
+
swapper = await fetchEthereumAddressForKeyGen(
|
|
3641
|
+
mpc,
|
|
3642
|
+
keyGen,
|
|
3643
|
+
args.nodeReadAuth ?? { bearerOnGet: true, jwt: null }
|
|
3644
|
+
);
|
|
3645
|
+
}
|
|
3646
|
+
const chainIdForGuard = parseUniswapChainId(resolveInputChainId(args));
|
|
3647
|
+
assertUniswapLimitOrderChain(chainIdForGuard);
|
|
3648
|
+
const base = args.baseUrl && args.baseUrl.trim() ? args.baseUrl.trim().replace(/\/$/, "") : "https://trade-api.gateway.uniswap.org/v1";
|
|
3649
|
+
const quoteUrl = `${base}${DEFAULT_LIMIT_ORDER_QUOTE_PATH}`;
|
|
3650
|
+
const body = buildLimitOrderQuoteRequestBody({ ...args, swapper });
|
|
3651
|
+
const headers = {
|
|
3652
|
+
...UNISWAP_QUOTE_HEADERS_BASE2,
|
|
3653
|
+
"x-api-key": apiKey
|
|
3654
|
+
};
|
|
3655
|
+
const fetchFn = args.fetchImpl ?? globalThis.fetch;
|
|
3656
|
+
const res = await fetchFn(quoteUrl, {
|
|
3657
|
+
method: "POST",
|
|
3658
|
+
headers,
|
|
3659
|
+
body: JSON.stringify(body),
|
|
3660
|
+
signal: args.signal
|
|
3661
|
+
});
|
|
3662
|
+
const text = await res.text();
|
|
3663
|
+
if (!res.ok) {
|
|
3664
|
+
throw new Error(messageFromUniswapHttpResponseBody(text, res.status, res.statusText));
|
|
3665
|
+
}
|
|
3666
|
+
const forParse = text.replace(/^\uFEFF/, "");
|
|
3667
|
+
try {
|
|
3668
|
+
return JSON.parse(forParse);
|
|
3669
|
+
} catch {
|
|
3670
|
+
throw new Error(
|
|
3671
|
+
`Limit order quote: ${messageFromUniswapHttpResponseBody(text, res.status, res.statusText)}`
|
|
3672
|
+
);
|
|
3673
|
+
}
|
|
3674
|
+
}
|
|
3675
|
+
function buildUniswapXLimitOrderSubmitBody(args) {
|
|
3676
|
+
const quote = args.quoteResponse.quote;
|
|
3677
|
+
if (quote == null || typeof quote !== "object" || Array.isArray(quote)) {
|
|
3678
|
+
throw new Error("limit order submit: quoteResponse.quote missing");
|
|
3679
|
+
}
|
|
3680
|
+
const routing = typeof args.quoteResponse.routing === "string" && args.quoteResponse.routing.trim() ? args.quoteResponse.routing.trim() : "LIMIT_ORDER";
|
|
3681
|
+
const chainId = args.quoteResponse.chainId ?? quote.chainId ?? UNISWAP_LIMIT_ORDER_CHAIN_ID;
|
|
3682
|
+
const quoteId = typeof args.quoteResponse.quoteId === "string" ? args.quoteResponse.quoteId : void 0;
|
|
3683
|
+
const requestId = typeof args.quoteResponse.requestId === "string" ? args.quoteResponse.requestId : void 0;
|
|
3684
|
+
return {
|
|
3685
|
+
signature: args.signatureHex.startsWith("0x") ? args.signatureHex : `0x${args.signatureHex}`,
|
|
3686
|
+
quote,
|
|
3687
|
+
chainId: parseUniswapChainId(chainId),
|
|
3688
|
+
orderType: "Limit",
|
|
3689
|
+
routing,
|
|
3690
|
+
...quoteId ? { quoteId } : {},
|
|
3691
|
+
...requestId ? { requestId } : {}
|
|
3692
|
+
};
|
|
3693
|
+
}
|
|
3694
|
+
async function submitUniswapXLimitOrder(args) {
|
|
3695
|
+
const apiKey = (args.uniswapApiKey || "").trim();
|
|
3696
|
+
if (!apiKey) {
|
|
3697
|
+
throw new Error("uniswapApiKey (x-api-key) is required");
|
|
3698
|
+
}
|
|
3699
|
+
const base = args.baseUrl && args.baseUrl.trim() ? args.baseUrl.trim().replace(/\/$/, "") : "https://trade-api.gateway.uniswap.org/v1";
|
|
3700
|
+
const orderUrl = `${base}${DEFAULT_ORDER_SUBMIT_PATH}`;
|
|
3701
|
+
const fetchFn = args.fetchImpl ?? globalThis.fetch;
|
|
3702
|
+
const res = await fetchFn(orderUrl, {
|
|
3703
|
+
method: "POST",
|
|
3704
|
+
headers: {
|
|
3705
|
+
"Content-Type": "application/json",
|
|
3706
|
+
"x-api-key": apiKey,
|
|
3707
|
+
"User-Agent": "ctm-mpc-defi uniswapLimitOrderSubmit/1.0 (TS)"
|
|
3708
|
+
},
|
|
3709
|
+
body: JSON.stringify(args.submitBody)
|
|
3710
|
+
});
|
|
3711
|
+
const text = await res.text();
|
|
3712
|
+
if (!res.ok) {
|
|
3713
|
+
throw new Error(messageFromUniswapHttpResponseBody(text, res.status, res.statusText));
|
|
3714
|
+
}
|
|
3715
|
+
const forParse = text.replace(/^\uFEFF/, "");
|
|
3716
|
+
try {
|
|
3717
|
+
return JSON.parse(forParse);
|
|
3718
|
+
} catch {
|
|
3719
|
+
throw new Error(
|
|
3720
|
+
`Limit order submit: ${messageFromUniswapHttpResponseBody(text, res.status, res.statusText)}`
|
|
3721
|
+
);
|
|
3722
|
+
}
|
|
3723
|
+
}
|
|
3724
|
+
async function fetchUniswapXLimitOrders(args) {
|
|
3725
|
+
const chainId = args.chainId ?? UNISWAP_LIMIT_ORDER_CHAIN_ID;
|
|
3726
|
+
assertUniswapLimitOrderChain(chainId);
|
|
3727
|
+
const base = args.baseUrl && args.baseUrl.trim() ? args.baseUrl.trim().replace(/\/$/, "") : DEFAULT_UNISWAPX_ORDER_BASE;
|
|
3728
|
+
const params = new URLSearchParams({
|
|
3729
|
+
chainId: String(chainId),
|
|
3730
|
+
swapper: trimAddr3(args.swapper)
|
|
3731
|
+
});
|
|
3732
|
+
if (args.limit != null && args.limit > 0) {
|
|
3733
|
+
params.set("limit", String(Math.floor(args.limit)));
|
|
3734
|
+
}
|
|
3735
|
+
const url = `${base}/limit-orders?${params.toString()}`;
|
|
3736
|
+
const headers = {
|
|
3737
|
+
Accept: "application/json",
|
|
3738
|
+
"User-Agent": "ctm-mpc-defi uniswapLimitOrdersList/1.0 (TS)"
|
|
3739
|
+
};
|
|
3740
|
+
const apiKey = (args.uniswapApiKey || "").trim();
|
|
3741
|
+
if (apiKey) {
|
|
3742
|
+
headers["x-api-key"] = apiKey;
|
|
3743
|
+
}
|
|
3744
|
+
const fetchFn = args.fetchImpl ?? globalThis.fetch;
|
|
3745
|
+
const res = await fetchFn(url, { method: "GET", headers });
|
|
3746
|
+
const text = await res.text();
|
|
3747
|
+
if (!res.ok) {
|
|
3748
|
+
const parsed = (() => {
|
|
3749
|
+
try {
|
|
3750
|
+
return JSON.parse(text);
|
|
3751
|
+
} catch {
|
|
3752
|
+
return null;
|
|
3753
|
+
}
|
|
3754
|
+
})();
|
|
3755
|
+
const msg = errorMessageFromUniswapJsonBody(parsed) ?? (text.trim() || res.statusText);
|
|
3756
|
+
throw new Error(`List limit orders HTTP ${res.status}: ${msg}`);
|
|
3757
|
+
}
|
|
3758
|
+
return JSON.parse(text.replace(/^\uFEFF/, ""));
|
|
3759
|
+
}
|
|
3760
|
+
async function uniswapFetchLimitOrdersMcp(args) {
|
|
3761
|
+
let swapper;
|
|
3762
|
+
if ((args.swapper || "").trim()) {
|
|
3763
|
+
swapper = trimAddr3(args.swapper);
|
|
3764
|
+
} else {
|
|
3765
|
+
const keyGen = (args.keyGen || "").trim();
|
|
3766
|
+
if (!keyGen) {
|
|
3767
|
+
throw new Error("swapper or keyGen is required");
|
|
3768
|
+
}
|
|
3769
|
+
const mpc = (args.managementNodeUrl || "").trim();
|
|
3770
|
+
if (!mpc) {
|
|
3771
|
+
throw new Error("managementNodeUrl is required when swapper is not provided");
|
|
3772
|
+
}
|
|
3773
|
+
swapper = await fetchEthereumAddressForKeyGen(
|
|
3774
|
+
mpc,
|
|
3775
|
+
keyGen,
|
|
3776
|
+
args.nodeReadAuth ?? { bearerOnGet: true, jwt: null }
|
|
3777
|
+
);
|
|
3778
|
+
}
|
|
3779
|
+
return fetchUniswapXLimitOrders({
|
|
3780
|
+
swapper,
|
|
3781
|
+
chainId: args.chainId,
|
|
3782
|
+
uniswapApiKey: args.uniswapApiKey,
|
|
3783
|
+
limit: args.limit,
|
|
3784
|
+
baseUrl: args.baseUrl,
|
|
3785
|
+
fetchImpl: args.fetchImpl
|
|
3786
|
+
});
|
|
3787
|
+
}
|
|
3788
|
+
var EIP712_SIGN_REQUEST_KIND = "eip712";
|
|
3789
|
+
function msgHashNo0x(digest) {
|
|
3790
|
+
return digest.startsWith("0x") ? digest.slice(2) : digest;
|
|
3791
|
+
}
|
|
3792
|
+
function eip712SignatureText(domain, primaryType) {
|
|
3793
|
+
return JSON.stringify({
|
|
3794
|
+
kind: "EIP-712",
|
|
3795
|
+
...typeof domain.name === "string" ? { name: domain.name } : {},
|
|
3796
|
+
primaryType
|
|
3797
|
+
});
|
|
3798
|
+
}
|
|
3799
|
+
function jsonStringifyForAudit(value) {
|
|
3800
|
+
return JSON.stringify(value, (_, v) => typeof v === "bigint" ? v.toString() : v);
|
|
3801
|
+
}
|
|
3802
|
+
function eip712MsgRawHex(typedData, delivery) {
|
|
3803
|
+
const envelope = {
|
|
3804
|
+
version: 1,
|
|
3805
|
+
...typedData,
|
|
3806
|
+
delivery
|
|
3807
|
+
};
|
|
3808
|
+
return viem.stringToHex(jsonStringifyForAudit(envelope));
|
|
3809
|
+
}
|
|
3810
|
+
function buildEip712MultisignBody(args) {
|
|
3811
|
+
const { typedData, delivery } = args;
|
|
3812
|
+
const digest = viem.hashTypedData({
|
|
3813
|
+
domain: typedData.domain,
|
|
3814
|
+
types: typedData.types,
|
|
3815
|
+
primaryType: typedData.primaryType,
|
|
3816
|
+
message: typedData.message
|
|
3817
|
+
});
|
|
3818
|
+
const extraJSON = {
|
|
3819
|
+
signRequestKind: EIP712_SIGN_REQUEST_KIND,
|
|
3820
|
+
eip712: {
|
|
3821
|
+
version: 1,
|
|
3822
|
+
digest,
|
|
3823
|
+
domain: typedData.domain,
|
|
3824
|
+
types: typedData.types,
|
|
3825
|
+
primaryType: typedData.primaryType,
|
|
3826
|
+
message: typedData.message
|
|
3827
|
+
},
|
|
3828
|
+
delivery
|
|
3829
|
+
};
|
|
3830
|
+
return finalizeMultisign({
|
|
3831
|
+
keyGen: args.keyGen,
|
|
3832
|
+
purposeText: args.purposeText,
|
|
3833
|
+
purposeSuffix: args.purposeSuffix,
|
|
3834
|
+
destinationChainID: args.destinationChainID,
|
|
3835
|
+
destinationAddress: args.destinationAddress,
|
|
3836
|
+
extraJSON,
|
|
3837
|
+
expiryDate: args.expiryDate,
|
|
3838
|
+
legs: [
|
|
3839
|
+
{
|
|
3840
|
+
msgHash: msgHashNo0x(digest),
|
|
3841
|
+
msgRaw: eip712MsgRawHex(typedData, delivery),
|
|
3842
|
+
destinationAddress: args.destinationAddress,
|
|
3843
|
+
signatureText: eip712SignatureText(typedData.domain, typedData.primaryType),
|
|
3844
|
+
audit: {
|
|
3845
|
+
kind: "EIP712",
|
|
3846
|
+
primaryType: typedData.primaryType,
|
|
3847
|
+
deliveryKind: delivery.kind,
|
|
3848
|
+
...args.audit ?? {}
|
|
3849
|
+
},
|
|
3850
|
+
feeSnapshot: {}
|
|
3851
|
+
}
|
|
3852
|
+
]
|
|
3853
|
+
});
|
|
3854
|
+
}
|
|
3855
|
+
|
|
3856
|
+
// src/protocols/evm/uniswap-v4/limitOrderMultisign.ts
|
|
3857
|
+
async function buildEvmMultisignBodyUniswapV4LimitOrderBatch(args) {
|
|
3858
|
+
assertUniswapLimitOrderChain(args.chainId);
|
|
3859
|
+
const permitRaw = extractPermitDataFromLimitQuote(args.fullLimitQuote);
|
|
3860
|
+
if (!permitRaw) {
|
|
3861
|
+
throw new Error(
|
|
3862
|
+
"Limit order quote has no permitData \u2014 cannot build EIP-712 sign request. Re-quote or confirm mainnet limit order support for this pair."
|
|
3863
|
+
);
|
|
3864
|
+
}
|
|
3865
|
+
const typedData = permitDataToEip712Payload(permitRaw);
|
|
3866
|
+
const submitTemplate = buildUniswapXLimitOrderSubmitBody({
|
|
3867
|
+
quoteResponse: args.fullLimitQuote,
|
|
3868
|
+
signatureHex: "0x"
|
|
3869
|
+
});
|
|
3870
|
+
return buildEip712MultisignBody({
|
|
3871
|
+
keyGen: args.keyGen,
|
|
3872
|
+
purposeText: args.purposeText,
|
|
3873
|
+
destinationChainID: String(UNISWAP_LIMIT_ORDER_CHAIN_ID),
|
|
3874
|
+
destinationAddress: PERMIT2_ADDRESS,
|
|
3875
|
+
typedData,
|
|
3876
|
+
delivery: {
|
|
3877
|
+
kind: "uniswapx_limit_order",
|
|
3878
|
+
chainId: UNISWAP_LIMIT_ORDER_CHAIN_ID,
|
|
3879
|
+
swapper: viem.getAddress(args.swapper),
|
|
3880
|
+
submitBodyTemplate: submitTemplate,
|
|
3881
|
+
quoteResponse: args.fullLimitQuote,
|
|
3882
|
+
uniswapApiKey: args.uniswapApiKey,
|
|
3883
|
+
tradeApiBaseUrl: args.tradeApiBaseUrl ?? "https://trade-api.gateway.uniswap.org/v1"
|
|
3884
|
+
},
|
|
3885
|
+
audit: {
|
|
3886
|
+
protocol: "uniswap-v4",
|
|
3887
|
+
action: "limitOrder",
|
|
3888
|
+
routing: args.fullLimitQuote.routing ?? "LIMIT_ORDER",
|
|
3889
|
+
orderType: "Limit",
|
|
3890
|
+
primaryType: typedData.primaryType
|
|
3891
|
+
},
|
|
3892
|
+
expiryDate: args.expiryDate
|
|
3893
|
+
});
|
|
3894
|
+
}
|
|
3895
|
+
async function buildEvmMultisignBodyUniswapV4LimitOrderBatchFromMcp(args) {
|
|
3896
|
+
return buildEvmMultisignBodyUniswapV4LimitOrderBatch({
|
|
3897
|
+
keyGen: args.keyGen,
|
|
3898
|
+
chainId: args.chainId,
|
|
3899
|
+
purposeText: args.purposeText,
|
|
3900
|
+
fullLimitQuote: args.fullLimitQuote,
|
|
3901
|
+
swapper: viem.getAddress(args.executorAddress),
|
|
3902
|
+
uniswapApiKey: args.uniswapApiKey,
|
|
3903
|
+
tradeApiBaseUrl: args.tradeApiBaseUrl,
|
|
3904
|
+
expiryDate: args.expiryDate
|
|
3905
|
+
});
|
|
3906
|
+
}
|
|
3907
|
+
|
|
3241
3908
|
// src/protocols/evm/uniswap-v4/index.ts
|
|
3242
3909
|
var UNISWAP_V4_PROTOCOL_ID = "uniswap-v4";
|
|
3243
3910
|
var uniswapV4ProtocolModule = {
|
|
@@ -3284,6 +3951,17 @@ var uniswapV4ProtocolModule = {
|
|
|
3284
3951
|
type: { type: "EXACT_INPUT | EXACT_OUTPUT", required: true, description: "Trade type" }
|
|
3285
3952
|
}
|
|
3286
3953
|
},
|
|
3954
|
+
{
|
|
3955
|
+
id: "uniswap-v4.limit-order",
|
|
3956
|
+
protocolId: UNISWAP_V4_PROTOCOL_ID,
|
|
3957
|
+
chainCategory: "evm",
|
|
3958
|
+
description: "Place UniswapX limit order via EIP-712 sign + POST /order (Ethereum mainnet only)",
|
|
3959
|
+
commonParams: ["keyGen", "purposeText"],
|
|
3960
|
+
params: {
|
|
3961
|
+
fullLimitQuote: { type: "object", required: true, description: "Full limit order quote from Trade API" },
|
|
3962
|
+
uniswapApiKey: { type: "string", required: true, description: "Uniswap Trade API key" }
|
|
3963
|
+
}
|
|
3964
|
+
},
|
|
3287
3965
|
{
|
|
3288
3966
|
id: "uniswap-v4.mint-liquidity",
|
|
3289
3967
|
protocolId: UNISWAP_V4_PROTOCOL_ID,
|
|
@@ -3339,6 +4017,10 @@ var uniswapV4 = {
|
|
|
3339
4017
|
swapExactInput,
|
|
3340
4018
|
swapFromQuote,
|
|
3341
4019
|
buildSwapMultisignBody: buildEvmMultisignBodyUniswapV4SkipPermit2Batch,
|
|
4020
|
+
limitOrderQuote: uniswapLimitOrderQuote,
|
|
4021
|
+
buildLimitOrderMultisignBody: buildEvmMultisignBodyUniswapV4LimitOrderBatchFromMcp,
|
|
4022
|
+
fetchLimitOrders: fetchUniswapXLimitOrders,
|
|
4023
|
+
fetchLimitOrdersMcp: uniswapFetchLimitOrdersMcp,
|
|
3342
4024
|
quote: uniswapTradeQuote,
|
|
3343
4025
|
createLiquidityPosition: uniswapLpCreatePosition,
|
|
3344
4026
|
increaseLiquidityPosition: uniswapLpIncreasePosition,
|
|
@@ -3352,12 +4034,22 @@ var uniswapV4 = {
|
|
|
3352
4034
|
isChainSupported: isUniswapV4ChainSupported
|
|
3353
4035
|
};
|
|
3354
4036
|
|
|
4037
|
+
exports.BITQUERY_API_KEY_DOCS_URL = BITQUERY_API_KEY_DOCS_URL;
|
|
4038
|
+
exports.BITQUERY_API_KEY_ENV = BITQUERY_API_KEY_ENV;
|
|
4039
|
+
exports.BITQUERY_API_KEY_SIGNUP_URL = BITQUERY_API_KEY_SIGNUP_URL;
|
|
4040
|
+
exports.BITQUERY_GRAPHQL_URL = BITQUERY_GRAPHQL_URL;
|
|
4041
|
+
exports.DEFAULT_LIMIT_ORDER_QUOTE_PATH = DEFAULT_LIMIT_ORDER_QUOTE_PATH;
|
|
4042
|
+
exports.DEFAULT_ORDER_SUBMIT_PATH = DEFAULT_ORDER_SUBMIT_PATH;
|
|
4043
|
+
exports.DEFAULT_UNISWAPX_ORDER_BASE = DEFAULT_UNISWAPX_ORDER_BASE;
|
|
3355
4044
|
exports.MAX_UINT160 = MAX_UINT160;
|
|
3356
4045
|
exports.MAX_UINT48 = MAX_UINT48;
|
|
3357
4046
|
exports.PERMIT2_ADDRESS = PERMIT2_ADDRESS;
|
|
4047
|
+
exports.ROBINHOOD_CHAIN_ID = ROBINHOOD_CHAIN_ID;
|
|
4048
|
+
exports.ROBINHOOD_WETH_ADDRESS = ROBINHOOD_WETH_ADDRESS;
|
|
3358
4049
|
exports.THE_GRAPH_API_KEY_DOCS_URL = THE_GRAPH_API_KEY_DOCS_URL;
|
|
3359
4050
|
exports.THE_GRAPH_API_KEY_ENV = THE_GRAPH_API_KEY_ENV;
|
|
3360
4051
|
exports.THE_GRAPH_API_KEY_SIGNUP_URL = THE_GRAPH_API_KEY_SIGNUP_URL;
|
|
4052
|
+
exports.UNISWAP_LIMIT_ORDER_CHAIN_ID = UNISWAP_LIMIT_ORDER_CHAIN_ID;
|
|
3361
4053
|
exports.UNISWAP_LP_API_BASE_DEFAULT = UNISWAP_LP_API_BASE_DEFAULT;
|
|
3362
4054
|
exports.UNISWAP_LP_DEFAULT_DEADLINE_SEC_OFFSET = UNISWAP_LP_DEFAULT_DEADLINE_SEC_OFFSET;
|
|
3363
4055
|
exports.UNISWAP_LP_DEFAULT_EXPIRY_MINUTES = UNISWAP_LP_DEFAULT_EXPIRY_MINUTES;
|
|
@@ -3382,26 +4074,36 @@ exports.UNISWAP_V4_PROTOCOL_ID = UNISWAP_V4_PROTOCOL_ID;
|
|
|
3382
4074
|
exports.UNISWAP_V4_SUBGRAPH_ID_BY_CHAIN_ID = UNISWAP_V4_SUBGRAPH_ID_BY_CHAIN_ID;
|
|
3383
4075
|
exports.aggregateOhlcvCandles = aggregateOhlcvCandles;
|
|
3384
4076
|
exports.applySlippagePercentToApproveWei = applySlippagePercentToApproveWei;
|
|
4077
|
+
exports.assertUniswapLimitOrderChain = assertUniswapLimitOrderChain;
|
|
3385
4078
|
exports.assertUniswapV4OhlcvInterval = assertUniswapV4OhlcvInterval;
|
|
3386
|
-
exports.
|
|
4079
|
+
exports.bitqueryApiKeyVariablesHint = bitqueryApiKeyVariablesHint;
|
|
4080
|
+
exports.bitqueryAuthErrorMessage = bitqueryAuthErrorMessage;
|
|
3387
4081
|
exports.buildEvmMultisignBodyUniswapV4CollectFeesBatch = buildEvmMultisignBodyUniswapV4CollectFeesBatch;
|
|
3388
4082
|
exports.buildEvmMultisignBodyUniswapV4DecreaseLiquidityBatch = buildEvmMultisignBodyUniswapV4DecreaseLiquidityBatch;
|
|
3389
4083
|
exports.buildEvmMultisignBodyUniswapV4IncreaseLiquidityBatch = buildEvmMultisignBodyUniswapV4IncreaseLiquidityBatch;
|
|
4084
|
+
exports.buildEvmMultisignBodyUniswapV4LimitOrderBatch = buildEvmMultisignBodyUniswapV4LimitOrderBatch;
|
|
4085
|
+
exports.buildEvmMultisignBodyUniswapV4LimitOrderBatchFromMcp = buildEvmMultisignBodyUniswapV4LimitOrderBatchFromMcp;
|
|
3390
4086
|
exports.buildEvmMultisignBodyUniswapV4MintLiquidityBatch = buildEvmMultisignBodyUniswapV4MintLiquidityBatch;
|
|
3391
4087
|
exports.buildEvmMultisignBodyUniswapV4SkipPermit2Batch = buildEvmMultisignBodyUniswapV4SkipPermit2Batch;
|
|
4088
|
+
exports.buildLimitOrderQuoteRequestBody = buildLimitOrderQuoteRequestBody;
|
|
3392
4089
|
exports.buildUniswapQuoteRequestBody = buildUniswapQuoteRequestBody;
|
|
3393
4090
|
exports.buildUniswapV4PurposePrefill = buildUniswapV4PurposePrefill;
|
|
4091
|
+
exports.buildUniswapXLimitOrderSubmitBody = buildUniswapXLimitOrderSubmitBody;
|
|
3394
4092
|
exports.computeUniswapV4PoolReference = computeUniswapV4PoolReference;
|
|
3395
4093
|
exports.computeUniswapV4Session = computeUniswapV4Session;
|
|
3396
4094
|
exports.createSwap = createSwap;
|
|
4095
|
+
exports.currencyFilterLabel = currencyFilterLabel;
|
|
3397
4096
|
exports.errorMessageFromUniswapJsonBody = errorMessageFromUniswapJsonBody;
|
|
4097
|
+
exports.extractPermitDataFromLimitQuote = extractPermitDataFromLimitQuote;
|
|
3398
4098
|
exports.extractUniswapLpTokenAmounts = extractUniswapLpTokenAmounts;
|
|
3399
4099
|
exports.extractUniswapLpTransaction = extractUniswapLpTransaction;
|
|
3400
4100
|
exports.fetchEthereumAddressForKeyGen = fetchEthereumAddressForKeyGen;
|
|
4101
|
+
exports.fetchRobinhoodBitqueryOhlcv = fetchRobinhoodBitqueryOhlcv;
|
|
3401
4102
|
exports.fetchUniswapV4PoolDayDatas = fetchUniswapV4PoolDayDatas;
|
|
3402
4103
|
exports.fetchUniswapV4PoolHourDatas = fetchUniswapV4PoolHourDatas;
|
|
3403
4104
|
exports.fetchUniswapV4PoolMeta = fetchUniswapV4PoolMeta;
|
|
3404
4105
|
exports.fetchUniswapV4Swaps = fetchUniswapV4Swaps;
|
|
4106
|
+
exports.fetchUniswapXLimitOrders = fetchUniswapXLimitOrders;
|
|
3405
4107
|
exports.formatUniswapAmountFieldFromWei = formatUniswapAmountFieldFromWei;
|
|
3406
4108
|
exports.formatUniswapLpAmountHuman = formatUniswapLpAmountHuman;
|
|
3407
4109
|
exports.formatUniswapPercentForUi = formatUniswapPercentForUi;
|
|
@@ -3409,27 +4111,40 @@ exports.formatUniswapQuoteForDisplay = formatUniswapQuoteForDisplay;
|
|
|
3409
4111
|
exports.formatUniswapV4PositionNotFoundError = formatUniswapV4PositionNotFoundError;
|
|
3410
4112
|
exports.getClassicQuoteFromStoredUniswapResponse = getClassicQuoteFromStoredUniswapResponse;
|
|
3411
4113
|
exports.getUniswapUniversalRouterSpenderOrThrow = getUniswapUniversalRouterSpenderOrThrow;
|
|
4114
|
+
exports.getUniswapUniversalRouterVersion = getUniswapUniversalRouterVersion;
|
|
3412
4115
|
exports.getUniswapV4PositionManagerDeployBlock = getUniswapV4PositionManagerDeployBlock;
|
|
3413
4116
|
exports.getUniswapV4PositionManagerOrThrow = getUniswapV4PositionManagerOrThrow;
|
|
4117
|
+
exports.isBitqueryAuthOrRateLimitError = isBitqueryAuthOrRateLimitError;
|
|
3414
4118
|
exports.isEthGetLogsBlockRangeTooLargeError = isEthGetLogsBlockRangeTooLargeError;
|
|
3415
4119
|
exports.isNativeUniswapLpTokenAddress = isNativeUniswapLpTokenAddress;
|
|
4120
|
+
exports.isRobinhoodOhlcvChain = isRobinhoodOhlcvChain;
|
|
3416
4121
|
exports.isTheGraphRateLimitOrAuthError = isTheGraphRateLimitOrAuthError;
|
|
3417
4122
|
exports.isUniswapFullQuoteResponseNativeIn = isUniswapFullQuoteResponseNativeIn;
|
|
4123
|
+
exports.isUniswapFullQuoteResponseNativeOut = isUniswapFullQuoteResponseNativeOut;
|
|
4124
|
+
exports.isUniswapLimitOrderChainSupported = isUniswapLimitOrderChainSupported;
|
|
4125
|
+
exports.isUniswapNativeTokenAddress = isUniswapNativeTokenAddress;
|
|
3418
4126
|
exports.isUniswapTokenInAddressNative = isUniswapTokenInAddressNative;
|
|
3419
4127
|
exports.isUniswapV4ChainSupported = isUniswapV4ChainSupported;
|
|
3420
4128
|
exports.isUniswapV4LiquidityEvmSignRequest = isUniswapV4LiquidityEvmSignRequest;
|
|
3421
4129
|
exports.isUniswapV4SwapEvmSignRequest = isUniswapV4SwapEvmSignRequest;
|
|
3422
4130
|
exports.listUniswapV4PositionsForWallet = listUniswapV4PositionsForWallet;
|
|
3423
4131
|
exports.listUniswapV4StandardLpPools = listUniswapV4StandardLpPools;
|
|
4132
|
+
exports.mapBitqueryOhlcvRowsToCandles = mapBitqueryOhlcvRowsToCandles;
|
|
3424
4133
|
exports.messageFromUniswapHttpResponseBody = messageFromUniswapHttpResponseBody;
|
|
3425
4134
|
exports.parseUniswapChainId = parseUniswapChainId;
|
|
3426
4135
|
exports.parseUniswapLpApiSnapshot = parseUniswapLpApiSnapshot;
|
|
3427
4136
|
exports.parseUniswapQuoteClassicInOut = parseUniswapQuoteClassicInOut;
|
|
3428
4137
|
exports.parseUniswapQuoteSlippageInfo = parseUniswapQuoteSlippageInfo;
|
|
3429
4138
|
exports.parseUniswapV4ScanFromDateYmd = parseUniswapV4ScanFromDateYmd;
|
|
4139
|
+
exports.permitDataToEip712Payload = permitDataToEip712Payload;
|
|
3430
4140
|
exports.quoteSwap = quoteSwap;
|
|
3431
4141
|
exports.readUniswapV4PositionInfoRaw = readUniswapV4PositionInfoRaw;
|
|
4142
|
+
exports.requireBitqueryApiKey = requireBitqueryApiKey;
|
|
4143
|
+
exports.resolveBitqueryApiKey = resolveBitqueryApiKey;
|
|
3432
4144
|
exports.resolveBlockAtOrAfterUnixTime = resolveBlockAtOrAfterUnixTime;
|
|
4145
|
+
exports.resolveChainIdFromStoredUniswapQuote = resolveChainIdFromStoredUniswapQuote;
|
|
4146
|
+
exports.resolveInputChainId = resolveInputChainId;
|
|
4147
|
+
exports.resolveRobinhoodChartCurrency = resolveRobinhoodChartCurrency;
|
|
3433
4148
|
exports.resolveRouterSwapGasUnitsFromSignRequest = resolveRouterSwapGasUnitsFromSignRequest;
|
|
3434
4149
|
exports.resolveTheGraphApiKey = resolveTheGraphApiKey;
|
|
3435
4150
|
exports.resolveUniswapV4LpExistingPoolFromKey = resolveUniswapV4LpExistingPoolFromKey;
|
|
@@ -3438,6 +4153,7 @@ exports.resolveUniswapV4OhlcvDataTier = resolveUniswapV4OhlcvDataTier;
|
|
|
3438
4153
|
exports.resolveUniswapV4OhlcvPool = resolveUniswapV4OhlcvPool;
|
|
3439
4154
|
exports.resolveUniswapV4PositionScanFromDate = resolveUniswapV4PositionScanFromDate;
|
|
3440
4155
|
exports.sortUniswapV4PoolCurrencies = sortUniswapV4PoolCurrencies;
|
|
4156
|
+
exports.submitUniswapXLimitOrder = submitUniswapXLimitOrder;
|
|
3441
4157
|
exports.swapExactInput = swapExactInput;
|
|
3442
4158
|
exports.swapFromQuote = swapFromQuote;
|
|
3443
4159
|
exports.swapTransactionDeadlineUnixFromExpiryMinutes = swapTransactionDeadlineUnixFromExpiryMinutes;
|
|
@@ -3445,6 +4161,8 @@ exports.theGraphApiKeyVariablesHint = theGraphApiKeyVariablesHint;
|
|
|
3445
4161
|
exports.theGraphRateLimitErrorMessage = theGraphRateLimitErrorMessage;
|
|
3446
4162
|
exports.tryGetUniswapV4PositionManager = tryGetUniswapV4PositionManager;
|
|
3447
4163
|
exports.uniswapCreateSwap = uniswapCreateSwap;
|
|
4164
|
+
exports.uniswapFetchLimitOrdersMcp = uniswapFetchLimitOrdersMcp;
|
|
4165
|
+
exports.uniswapLimitOrderQuote = uniswapLimitOrderQuote;
|
|
3448
4166
|
exports.uniswapLpClaimFees = uniswapLpClaimFees;
|
|
3449
4167
|
exports.uniswapLpCreatePosition = uniswapLpCreatePosition;
|
|
3450
4168
|
exports.uniswapLpDecreasePosition = uniswapLpDecreasePosition;
|
|
@@ -3459,6 +4177,7 @@ exports.uniswapV4ListPositionsFromRegistryForMcp = uniswapV4ListPositionsFromReg
|
|
|
3459
4177
|
exports.uniswapV4ListPositionsRegistryMcpPlaceholder = uniswapV4ListPositionsRegistryMcpPlaceholder;
|
|
3460
4178
|
exports.uniswapV4ListStandardLpPools = uniswapV4ListStandardLpPools;
|
|
3461
4179
|
exports.uniswapV4OhlcvIntervalToBucketSec = uniswapV4OhlcvIntervalToBucketSec;
|
|
4180
|
+
exports.uniswapV4OhlcvSupportedChainIds = uniswapV4OhlcvSupportedChainIds;
|
|
3462
4181
|
exports.uniswapV4PositionMintedTokenIdsFromReceipt = uniswapV4PositionMintedTokenIdsFromReceipt;
|
|
3463
4182
|
exports.uniswapV4ProtocolModule = uniswapV4ProtocolModule;
|
|
3464
4183
|
exports.uniswapV4RegisterPositionFromMintTxPlaceholder = uniswapV4RegisterPositionFromMintTxPlaceholder;
|