@continuumdao/ctm-mpc-defi 0.2.22 → 0.2.25
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 +806 -18
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +2400 -43
- package/dist/agent/catalog.js +772 -19
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/arcus/SKILL.md +72 -0
- package/dist/agent/skills/gmx/SKILL.md +32 -0
- package/dist/agent/skills/hyperliquid/SKILL.md +44 -3
- package/dist/agent/skills/uniswap-v4/SKILL.md +31 -1
- package/dist/core/index.cjs +55 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +15 -21
- package/dist/core/index.js +54 -1
- package/dist/core/index.js.map +1 -1
- package/dist/eip712Multisign-xhXpUYp3.d.ts +36 -0
- package/dist/index.cjs +399 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +398 -13
- package/dist/index.js.map +1 -1
- package/dist/protocols/evm/arcus/index.cjs +2061 -0
- package/dist/protocols/evm/arcus/index.cjs.map +1 -0
- package/dist/protocols/evm/arcus/index.d.ts +726 -0
- package/dist/protocols/evm/arcus/index.js +1964 -0
- package/dist/protocols/evm/arcus/index.js.map +1 -0
- 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 +6 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { C as ChainCategory, a as ChainSupportContext, E as EvmTokenKind, K as KeyGenSubset, b as KeyGenSubsetForPermit, M as MultisignBuildResult, c as MultisignCommonArgs, N as NearTokenKind, P as ParamDoc, d as ProtocolActionDescriptor, e as ProtocolModule, S as SolanaTokenKind, T as TokenRef } from './types-PZrvtjv8.js';
|
|
2
2
|
export { getClientIdFromKeyGenResult as firstClientIdFromKeyGen } from '@continuumdao/continuum-node-sdk';
|
|
3
|
-
export {
|
|
3
|
+
export { BuildPayloadSignEd25519MultisignBodyArgs, DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS, DEFI_PROTOCOLS_WITH_30MIN_EXPIRY, PAYLOAD_SIGN_ED25519_REQUEST_KIND, PayloadSignEd25519Delivery, buildPayloadSignEd25519MultisignBody, defiMultisignExpiryUnixSeconds, getAaveGraphqlProxyUrl, getCoingeckoProxyUrl, getEulerGraphqlProxyUrl, getMapleGraphqlProxyUrl, getMorphoGraphqlProxyUrl, mergePurposeText, postJsonViaOptionalProxy, setAaveGraphqlProxyUrl, setCoingeckoProxyUrl, setEulerGraphqlProxyUrl, setMapleGraphqlProxyUrl, setMorphoGraphqlProxyUrl } from './core/index.js';
|
|
4
4
|
export { C as ChainCategoryBuildInput, a as ChainCategoryModule, M as MultisignLeg, c as coreChainCategoryModule, f as finalizeMultisign } from './envelope-C_bfuKab.js';
|
|
5
5
|
export { g as getActionsByChainCategory, a as getProtocolModule, b as getProtocolModules, r as registerProtocolModule } from './registry-DxDSPQ-p.js';
|
|
6
|
+
export { B as BuildEip712MultisignBodyArgs, E as EIP712_SIGN_REQUEST_KIND, a as Eip712MultisignDelivery, b as Eip712TypedDataField, c as Eip712TypedDataPayload, d as buildEip712MultisignBody } from './eip712Multisign-xhXpUYp3.js';
|
|
6
7
|
export { E as EvmChainDetail, a as EvmProtocolContext, b as EvmTxStep, i as isEvmNativeToken, m as matchEvmTokenKind } from './types-RZWOTm8c.js';
|
|
7
8
|
export { COINGECKO_PLATFORM_BY_CHAIN_ID, ConditionalApproveStep, EvmBatchMetaBuilder, EvmBuildBatchArgs, approveStepsToEvmTxSteps, buildConditionalErc20ApproveSteps, buildEvmMultisignBatch, coingeckoPlatformForChainId, evmChainCategoryModule, normalizeCurveRouterAmountString, normalizeHumanDecimalAmount, parseEvmChainIdToNumber, publicClientForRpc, resolveErc20Decimals, routerSwapGasLimitFromEstimate } from './chains/evm/index.js';
|
|
8
9
|
export { SOLANA_CHAIN_CATEGORY, solanaChainCategoryModule } from './chains/solana/index.js';
|
package/dist/index.js
CHANGED
|
@@ -218,6 +218,58 @@ function buildEip712MultisignBody(args) {
|
|
|
218
218
|
]
|
|
219
219
|
});
|
|
220
220
|
}
|
|
221
|
+
var PAYLOAD_SIGN_ED25519_REQUEST_KIND = "payload_sign_ed25519";
|
|
222
|
+
function msgHashNo0xFromBytes(bytes) {
|
|
223
|
+
return Buffer.from(bytes).toString("hex");
|
|
224
|
+
}
|
|
225
|
+
function payloadMsgRawHex(messageUtf8, delivery) {
|
|
226
|
+
const envelope = {
|
|
227
|
+
version: 1,
|
|
228
|
+
messageUtf8,
|
|
229
|
+
delivery
|
|
230
|
+
};
|
|
231
|
+
return stringToHex(JSON.stringify(envelope));
|
|
232
|
+
}
|
|
233
|
+
function buildPayloadSignEd25519MultisignBody(args) {
|
|
234
|
+
const messageBytes = Buffer.from(args.messageUtf8, "utf8");
|
|
235
|
+
const msgHash = msgHashNo0xFromBytes(messageBytes);
|
|
236
|
+
const extraJSON = {
|
|
237
|
+
signRequestKind: PAYLOAD_SIGN_ED25519_REQUEST_KIND,
|
|
238
|
+
payloadSignEd25519: {
|
|
239
|
+
version: 1,
|
|
240
|
+
messageHex: msgHash,
|
|
241
|
+
messageLength: messageBytes.length
|
|
242
|
+
},
|
|
243
|
+
delivery: args.delivery
|
|
244
|
+
};
|
|
245
|
+
if (args.billingKeyGenPubKey?.trim()) {
|
|
246
|
+
extraJSON.billingKeyGenPubKey = args.billingKeyGenPubKey.trim();
|
|
247
|
+
}
|
|
248
|
+
return finalizeMultisign({
|
|
249
|
+
keyGen: args.keyGen,
|
|
250
|
+
purposeText: args.purposeText,
|
|
251
|
+
purposeSuffix: args.purposeSuffix,
|
|
252
|
+
destinationChainID: args.destinationChainID,
|
|
253
|
+
destinationAddress: args.destinationAddress,
|
|
254
|
+
extraJSON,
|
|
255
|
+
expiryDate: args.expiryDate,
|
|
256
|
+
legs: [
|
|
257
|
+
{
|
|
258
|
+
msgHash,
|
|
259
|
+
msgRaw: payloadMsgRawHex(args.messageUtf8, args.delivery),
|
|
260
|
+
destinationAddress: args.destinationAddress,
|
|
261
|
+
signatureText: args.signatureText ?? "Arcus Ed25519 payload sign",
|
|
262
|
+
audit: {
|
|
263
|
+
kind: "PAYLOAD_SIGN_ED25519",
|
|
264
|
+
deliveryKind: args.delivery.kind,
|
|
265
|
+
messageLength: messageBytes.length,
|
|
266
|
+
...args.audit ?? {}
|
|
267
|
+
},
|
|
268
|
+
feeSnapshot: {}
|
|
269
|
+
}
|
|
270
|
+
]
|
|
271
|
+
});
|
|
272
|
+
}
|
|
221
273
|
|
|
222
274
|
// src/core/expiry.ts
|
|
223
275
|
var DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS = 30 * 60;
|
|
@@ -225,6 +277,7 @@ var DEFI_PROTOCOLS_WITH_30MIN_EXPIRY = /* @__PURE__ */ new Set([
|
|
|
225
277
|
"uniswap-v4",
|
|
226
278
|
"gmx",
|
|
227
279
|
"hyperliquid",
|
|
280
|
+
"arcus",
|
|
228
281
|
"curve-dao"
|
|
229
282
|
]);
|
|
230
283
|
function defiMultisignExpiryUnixSeconds(protocolId, explicitExpiryDate) {
|
|
@@ -615,8 +668,18 @@ var UNIVERSAL_ROUTER_SPENDER = {
|
|
|
615
668
|
143: "0x0d97dc33264bfc1c226207428a79b26757fb9dc3",
|
|
616
669
|
59144: "0x661e93cca42afacb172121ef892830ca3b70f08d",
|
|
617
670
|
4217: "0x1febb76be10aaf3a1402f04e8e835f2c382f7914",
|
|
618
|
-
196: "0x5507749f2c558bb3e162c6e90c314c092e7372ff"
|
|
671
|
+
196: "0x5507749f2c558bb3e162c6e90c314c092e7372ff",
|
|
672
|
+
/** Robinhood Chain mainnet — Universal Router v2.1.1 (Trade API / interface) */
|
|
673
|
+
4663: "0x8876789976decbfcbbbe364623c63652db8c0904"
|
|
674
|
+
};
|
|
675
|
+
var UNIVERSAL_ROUTER_VERSION_BY_CHAIN = {
|
|
676
|
+
/** Robinhood has UR 2.1.1 only in the supported-chains table (no 2.0 Trade API column). */
|
|
677
|
+
4663: "2.1.1"
|
|
619
678
|
};
|
|
679
|
+
function getUniswapUniversalRouterVersion(chainId) {
|
|
680
|
+
const v = UNIVERSAL_ROUTER_VERSION_BY_CHAIN[chainId];
|
|
681
|
+
return typeof v === "string" && v.trim() ? v.trim() : UNISWAP_UNIVERSAL_ROUTER_VERSION_DEFAULT;
|
|
682
|
+
}
|
|
620
683
|
function isUniswapV4ChainSupported(chainId) {
|
|
621
684
|
if (chainId == null) return false;
|
|
622
685
|
const n = parseEvmChainIdToNumber(chainId);
|
|
@@ -651,7 +714,9 @@ var POSITION_MANAGER_BY_CHAIN = {
|
|
|
651
714
|
11155111: "0x4B2C77d209D3405F41a037Ec6c77F7F5b8e2ca80",
|
|
652
715
|
130: "0x0d97dc33264bfc1c226207428a79b26757fb9dc3",
|
|
653
716
|
1868: "0x0e2850543f69f678257266e0907ff9a58b3f13de",
|
|
654
|
-
59144: "0x661e93cca42afacb172121ef892830ca3b70f08d"
|
|
717
|
+
59144: "0x661e93cca42afacb172121ef892830ca3b70f08d",
|
|
718
|
+
/** Robinhood Chain mainnet */
|
|
719
|
+
4663: "0x58daec3116aae6D93017bAAea7749052E8a04fA7"
|
|
655
720
|
};
|
|
656
721
|
function getUniswapV4PositionManagerOrThrow(chainId) {
|
|
657
722
|
const raw = POSITION_MANAGER_BY_CHAIN[chainId];
|
|
@@ -698,8 +763,8 @@ function parseUniswapChainId(value) {
|
|
|
698
763
|
function trimAddr(a) {
|
|
699
764
|
return a.trim();
|
|
700
765
|
}
|
|
701
|
-
function
|
|
702
|
-
const t = (
|
|
766
|
+
function isUniswapNativeTokenAddress(token) {
|
|
767
|
+
const t = (token ?? "").toString().trim();
|
|
703
768
|
if (!t) return false;
|
|
704
769
|
try {
|
|
705
770
|
return getAddress(t) === zeroAddress;
|
|
@@ -714,7 +779,16 @@ function isUniswapFullQuoteResponseNativeIn(stored) {
|
|
|
714
779
|
const input = q.input;
|
|
715
780
|
if (!input) return false;
|
|
716
781
|
const raw = (input.address ?? input.token ?? "").toString().trim();
|
|
717
|
-
return
|
|
782
|
+
return isUniswapNativeTokenAddress(raw);
|
|
783
|
+
}
|
|
784
|
+
function isUniswapFullQuoteResponseNativeOut(stored) {
|
|
785
|
+
if (!stored) return false;
|
|
786
|
+
const q = stored.quote;
|
|
787
|
+
if (!q || typeof q !== "object" || Array.isArray(q)) return false;
|
|
788
|
+
const output = q.output;
|
|
789
|
+
if (!output) return false;
|
|
790
|
+
const raw = (output.address ?? output.token ?? "").toString().trim();
|
|
791
|
+
return isUniswapNativeTokenAddress(raw);
|
|
718
792
|
}
|
|
719
793
|
async function fetchEthereumAddressForKeyGen(managementNodeUrl, keyGenId, readAuth = { bearerOnGet: true, jwt: null }, init) {
|
|
720
794
|
const base = managementNodeUrl.trim().replace(/\/$/, "");
|
|
@@ -776,6 +850,31 @@ function buildUniswapQuoteRequestBody(args) {
|
|
|
776
850
|
}
|
|
777
851
|
return body;
|
|
778
852
|
}
|
|
853
|
+
function resolveChainIdFromStoredUniswapQuote(stored) {
|
|
854
|
+
if (!stored) return 0;
|
|
855
|
+
const top = stored;
|
|
856
|
+
for (const key of ["tokenInChainId", "chainId"]) {
|
|
857
|
+
const raw = top[key];
|
|
858
|
+
if (raw != null && String(raw).trim() !== "") {
|
|
859
|
+
try {
|
|
860
|
+
return parseUniswapChainId(raw);
|
|
861
|
+
} catch {
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
const q = top.quote;
|
|
866
|
+
if (q && typeof q === "object" && !Array.isArray(q)) {
|
|
867
|
+
const input = q.input;
|
|
868
|
+
const chain = input?.chainId;
|
|
869
|
+
if (chain != null && String(chain).trim() !== "") {
|
|
870
|
+
try {
|
|
871
|
+
return parseUniswapChainId(chain);
|
|
872
|
+
} catch {
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
return 0;
|
|
877
|
+
}
|
|
779
878
|
function errorMessageFromUniswapJsonBody(value) {
|
|
780
879
|
if (value == null) return null;
|
|
781
880
|
if (typeof value === "string") {
|
|
@@ -888,16 +987,18 @@ async function uniswapTradeQuote(args) {
|
|
|
888
987
|
}
|
|
889
988
|
const base = args.baseUrl && args.baseUrl.trim() ? args.baseUrl.trim().replace(/\/$/, "") : DEFAULT_TRADE_BASE;
|
|
890
989
|
const quoteUrl = `${base}/quote`;
|
|
891
|
-
const
|
|
990
|
+
const chainIdForRouter = parseUniswapChainId(resolveInputChainId(args));
|
|
991
|
+
const urv = args.universalRouterVersion && args.universalRouterVersion.trim() || getUniswapUniversalRouterVersion(chainIdForRouter);
|
|
892
992
|
const body = buildUniswapQuoteRequestBody({ ...args, swapper });
|
|
893
|
-
const nativeIn =
|
|
993
|
+
const nativeIn = isUniswapNativeTokenAddress(args.tokenIn);
|
|
994
|
+
const nativeOut = isUniswapNativeTokenAddress(args.tokenOut);
|
|
894
995
|
const headers = {
|
|
895
996
|
...UNISWAP_QUOTE_HEADERS_BASE,
|
|
896
997
|
"x-api-key": apiKey,
|
|
897
998
|
"x-universal-router-version": urv,
|
|
898
999
|
"x-permit2-disabled": args.permit2Disabled === true ? "true" : "false",
|
|
899
|
-
/** Native (0x0)
|
|
900
|
-
"x-erc20eth-enabled": nativeIn ? "true" : "false"
|
|
1000
|
+
/** Native (0x0) in or out: enables ERC20↔ETH routes (incl. UniswapX on Robinhood). */
|
|
1001
|
+
"x-erc20eth-enabled": nativeIn || nativeOut ? "true" : "false"
|
|
901
1002
|
};
|
|
902
1003
|
const fetchFn = args.fetchImpl ?? globalThis.fetch;
|
|
903
1004
|
const res = await fetchFn(quoteUrl, {
|
|
@@ -908,7 +1009,11 @@ async function uniswapTradeQuote(args) {
|
|
|
908
1009
|
});
|
|
909
1010
|
const text = await res.text();
|
|
910
1011
|
if (!res.ok) {
|
|
911
|
-
|
|
1012
|
+
let msg = messageFromUniswapHttpResponseBody(text, res.status, res.statusText);
|
|
1013
|
+
if (res.status === 404 && chainIdForRouter === 4663) {
|
|
1014
|
+
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).";
|
|
1015
|
+
}
|
|
1016
|
+
throw new Error(msg);
|
|
912
1017
|
}
|
|
913
1018
|
const forParse = text.replace(/^\uFEFF/, "");
|
|
914
1019
|
try {
|
|
@@ -1015,16 +1120,17 @@ async function uniswapCreateSwap(args) {
|
|
|
1015
1120
|
quote: classic,
|
|
1016
1121
|
deadline
|
|
1017
1122
|
};
|
|
1018
|
-
const urv = (args.universalRouterVersion ??
|
|
1123
|
+
const urv = (args.universalRouterVersion ?? "").trim() || getUniswapUniversalRouterVersion(resolveChainIdFromStoredUniswapQuote(args.fullQuoteFromPermit));
|
|
1019
1124
|
const fn = args.fetchImpl ?? globalThis.fetch;
|
|
1020
1125
|
const nativeIn = isUniswapFullQuoteResponseNativeIn(args.fullQuoteFromPermit);
|
|
1126
|
+
const nativeOut = isUniswapFullQuoteResponseNativeOut(args.fullQuoteFromPermit);
|
|
1021
1127
|
const res = await fn(url, {
|
|
1022
1128
|
method: "POST",
|
|
1023
1129
|
headers: {
|
|
1024
1130
|
"Content-Type": "application/json",
|
|
1025
1131
|
"x-api-key": args.uniswapApiKey.trim(),
|
|
1026
1132
|
"x-universal-router-version": urv,
|
|
1027
|
-
"x-erc20eth-enabled": nativeIn ? "true" : "false",
|
|
1133
|
+
"x-erc20eth-enabled": nativeIn || nativeOut ? "true" : "false",
|
|
1028
1134
|
"x-permit2-disabled": "true"
|
|
1029
1135
|
},
|
|
1030
1136
|
body: JSON.stringify(body)
|
|
@@ -2224,6 +2330,270 @@ async function swapExactInput(args) {
|
|
|
2224
2330
|
return swapFromQuote({ ...args, swap });
|
|
2225
2331
|
}
|
|
2226
2332
|
|
|
2333
|
+
// src/protocols/evm/uniswap-v4/limitOrder.ts
|
|
2334
|
+
function trimAddr3(a) {
|
|
2335
|
+
return a.trim();
|
|
2336
|
+
}
|
|
2337
|
+
var UNISWAP_LIMIT_ORDER_CHAIN_ID = 1;
|
|
2338
|
+
var DEFAULT_UNISWAPX_ORDER_BASE = "https://api.uniswap.org/v2";
|
|
2339
|
+
var DEFAULT_LIMIT_ORDER_QUOTE_PATH = "/limit_order_quote";
|
|
2340
|
+
var UNISWAP_QUOTE_HEADERS_BASE2 = {
|
|
2341
|
+
"Content-Type": "application/json",
|
|
2342
|
+
"User-Agent": "ctm-mpc-defi uniswapLimitOrderQuote/1.0 (TS)"
|
|
2343
|
+
};
|
|
2344
|
+
function isUniswapLimitOrderChainSupported(chainId) {
|
|
2345
|
+
return parseUniswapChainId(chainId) === UNISWAP_LIMIT_ORDER_CHAIN_ID;
|
|
2346
|
+
}
|
|
2347
|
+
function assertUniswapLimitOrderChain(chainId) {
|
|
2348
|
+
if (!isUniswapLimitOrderChainSupported(chainId)) {
|
|
2349
|
+
throw new Error(
|
|
2350
|
+
`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.`
|
|
2351
|
+
);
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
function inferPrimaryTypeFromPermitTypes(types) {
|
|
2355
|
+
for (const key of Object.keys(types)) {
|
|
2356
|
+
if (key !== "EIP712Domain") {
|
|
2357
|
+
return key;
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
throw new Error("permitData.types missing primaryType (no non-EIP712Domain entry)");
|
|
2361
|
+
}
|
|
2362
|
+
function permitDataToEip712Payload(permitData) {
|
|
2363
|
+
const domain = permitData.domain;
|
|
2364
|
+
const types = permitData.types;
|
|
2365
|
+
const message = permitData.values ?? permitData.message;
|
|
2366
|
+
if (domain == null || typeof domain !== "object" || Array.isArray(domain)) {
|
|
2367
|
+
throw new Error("limit order quote: permitData.domain missing");
|
|
2368
|
+
}
|
|
2369
|
+
if (types == null || typeof types !== "object" || Array.isArray(types)) {
|
|
2370
|
+
throw new Error("limit order quote: permitData.types missing");
|
|
2371
|
+
}
|
|
2372
|
+
if (message == null || typeof message !== "object" || Array.isArray(message)) {
|
|
2373
|
+
throw new Error("limit order quote: permitData.values (message) missing");
|
|
2374
|
+
}
|
|
2375
|
+
const primaryType = typeof permitData.primaryType === "string" && permitData.primaryType.trim() ? permitData.primaryType.trim() : inferPrimaryTypeFromPermitTypes(
|
|
2376
|
+
types
|
|
2377
|
+
);
|
|
2378
|
+
return {
|
|
2379
|
+
domain,
|
|
2380
|
+
types,
|
|
2381
|
+
primaryType,
|
|
2382
|
+
message
|
|
2383
|
+
};
|
|
2384
|
+
}
|
|
2385
|
+
function extractPermitDataFromLimitQuote(quoteResponse) {
|
|
2386
|
+
const permitData = quoteResponse.permitData;
|
|
2387
|
+
if (permitData == null) return null;
|
|
2388
|
+
if (typeof permitData !== "object" || Array.isArray(permitData)) {
|
|
2389
|
+
throw new Error("limit order quote: permitData is not an object");
|
|
2390
|
+
}
|
|
2391
|
+
return permitData;
|
|
2392
|
+
}
|
|
2393
|
+
function buildLimitOrderQuoteRequestBody(args) {
|
|
2394
|
+
const base = buildUniswapQuoteRequestBody({
|
|
2395
|
+
type: args.type,
|
|
2396
|
+
amount: args.amount,
|
|
2397
|
+
tokenIn: args.tokenIn,
|
|
2398
|
+
tokenOut: args.tokenOut,
|
|
2399
|
+
chainId: args.chainId,
|
|
2400
|
+
tokenInChainId: args.tokenInChainId,
|
|
2401
|
+
tokenOutChainId: args.tokenOutChainId,
|
|
2402
|
+
swapper: args.swapper
|
|
2403
|
+
});
|
|
2404
|
+
assertUniswapLimitOrderChain(base.tokenInChainId);
|
|
2405
|
+
return {
|
|
2406
|
+
...base,
|
|
2407
|
+
limitPrice: String(args.limitPrice).trim(),
|
|
2408
|
+
orderDeadline: args.orderDeadline
|
|
2409
|
+
};
|
|
2410
|
+
}
|
|
2411
|
+
async function uniswapLimitOrderQuote(args) {
|
|
2412
|
+
const apiKey = (args.uniswapApiKey || "").trim();
|
|
2413
|
+
if (!apiKey) {
|
|
2414
|
+
throw new Error("uniswapApiKey (x-api-key) is required");
|
|
2415
|
+
}
|
|
2416
|
+
let swapper;
|
|
2417
|
+
if ((args.swapper || "").trim()) {
|
|
2418
|
+
swapper = trimAddr3(args.swapper);
|
|
2419
|
+
} else {
|
|
2420
|
+
const keyGen = (args.keyGen || "").trim();
|
|
2421
|
+
if (!keyGen) {
|
|
2422
|
+
throw new Error("keyGen is required when swapper is not provided");
|
|
2423
|
+
}
|
|
2424
|
+
const mpc = (args.managementNodeUrl || "").trim();
|
|
2425
|
+
if (!mpc) {
|
|
2426
|
+
throw new Error("managementNodeUrl is required when swapper is not provided (to resolve keyGen)");
|
|
2427
|
+
}
|
|
2428
|
+
swapper = await fetchEthereumAddressForKeyGen(
|
|
2429
|
+
mpc,
|
|
2430
|
+
keyGen,
|
|
2431
|
+
args.nodeReadAuth ?? { bearerOnGet: true, jwt: null }
|
|
2432
|
+
);
|
|
2433
|
+
}
|
|
2434
|
+
const chainIdForGuard = parseUniswapChainId(resolveInputChainId(args));
|
|
2435
|
+
assertUniswapLimitOrderChain(chainIdForGuard);
|
|
2436
|
+
const base = args.baseUrl && args.baseUrl.trim() ? args.baseUrl.trim().replace(/\/$/, "") : "https://trade-api.gateway.uniswap.org/v1";
|
|
2437
|
+
const quoteUrl = `${base}${DEFAULT_LIMIT_ORDER_QUOTE_PATH}`;
|
|
2438
|
+
const body = buildLimitOrderQuoteRequestBody({ ...args, swapper });
|
|
2439
|
+
const headers = {
|
|
2440
|
+
...UNISWAP_QUOTE_HEADERS_BASE2,
|
|
2441
|
+
"x-api-key": apiKey
|
|
2442
|
+
};
|
|
2443
|
+
const fetchFn = args.fetchImpl ?? globalThis.fetch;
|
|
2444
|
+
const res = await fetchFn(quoteUrl, {
|
|
2445
|
+
method: "POST",
|
|
2446
|
+
headers,
|
|
2447
|
+
body: JSON.stringify(body),
|
|
2448
|
+
signal: args.signal
|
|
2449
|
+
});
|
|
2450
|
+
const text = await res.text();
|
|
2451
|
+
if (!res.ok) {
|
|
2452
|
+
throw new Error(messageFromUniswapHttpResponseBody(text, res.status, res.statusText));
|
|
2453
|
+
}
|
|
2454
|
+
const forParse = text.replace(/^\uFEFF/, "");
|
|
2455
|
+
try {
|
|
2456
|
+
return JSON.parse(forParse);
|
|
2457
|
+
} catch {
|
|
2458
|
+
throw new Error(
|
|
2459
|
+
`Limit order quote: ${messageFromUniswapHttpResponseBody(text, res.status, res.statusText)}`
|
|
2460
|
+
);
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
function buildUniswapXLimitOrderSubmitBody(args) {
|
|
2464
|
+
const quote = args.quoteResponse.quote;
|
|
2465
|
+
if (quote == null || typeof quote !== "object" || Array.isArray(quote)) {
|
|
2466
|
+
throw new Error("limit order submit: quoteResponse.quote missing");
|
|
2467
|
+
}
|
|
2468
|
+
const routing = typeof args.quoteResponse.routing === "string" && args.quoteResponse.routing.trim() ? args.quoteResponse.routing.trim() : "LIMIT_ORDER";
|
|
2469
|
+
const chainId = args.quoteResponse.chainId ?? quote.chainId ?? UNISWAP_LIMIT_ORDER_CHAIN_ID;
|
|
2470
|
+
const quoteId = typeof args.quoteResponse.quoteId === "string" ? args.quoteResponse.quoteId : void 0;
|
|
2471
|
+
const requestId = typeof args.quoteResponse.requestId === "string" ? args.quoteResponse.requestId : void 0;
|
|
2472
|
+
return {
|
|
2473
|
+
signature: args.signatureHex.startsWith("0x") ? args.signatureHex : `0x${args.signatureHex}`,
|
|
2474
|
+
quote,
|
|
2475
|
+
chainId: parseUniswapChainId(chainId),
|
|
2476
|
+
orderType: "Limit",
|
|
2477
|
+
routing,
|
|
2478
|
+
...quoteId ? { quoteId } : {},
|
|
2479
|
+
...requestId ? { requestId } : {}
|
|
2480
|
+
};
|
|
2481
|
+
}
|
|
2482
|
+
async function fetchUniswapXLimitOrders(args) {
|
|
2483
|
+
const chainId = args.chainId ?? UNISWAP_LIMIT_ORDER_CHAIN_ID;
|
|
2484
|
+
assertUniswapLimitOrderChain(chainId);
|
|
2485
|
+
const base = args.baseUrl && args.baseUrl.trim() ? args.baseUrl.trim().replace(/\/$/, "") : DEFAULT_UNISWAPX_ORDER_BASE;
|
|
2486
|
+
const params = new URLSearchParams({
|
|
2487
|
+
chainId: String(chainId),
|
|
2488
|
+
swapper: trimAddr3(args.swapper)
|
|
2489
|
+
});
|
|
2490
|
+
if (args.limit != null && args.limit > 0) {
|
|
2491
|
+
params.set("limit", String(Math.floor(args.limit)));
|
|
2492
|
+
}
|
|
2493
|
+
const url = `${base}/limit-orders?${params.toString()}`;
|
|
2494
|
+
const headers = {
|
|
2495
|
+
Accept: "application/json",
|
|
2496
|
+
"User-Agent": "ctm-mpc-defi uniswapLimitOrdersList/1.0 (TS)"
|
|
2497
|
+
};
|
|
2498
|
+
const apiKey = (args.uniswapApiKey || "").trim();
|
|
2499
|
+
if (apiKey) {
|
|
2500
|
+
headers["x-api-key"] = apiKey;
|
|
2501
|
+
}
|
|
2502
|
+
const fetchFn = args.fetchImpl ?? globalThis.fetch;
|
|
2503
|
+
const res = await fetchFn(url, { method: "GET", headers });
|
|
2504
|
+
const text = await res.text();
|
|
2505
|
+
if (!res.ok) {
|
|
2506
|
+
const parsed = (() => {
|
|
2507
|
+
try {
|
|
2508
|
+
return JSON.parse(text);
|
|
2509
|
+
} catch {
|
|
2510
|
+
return null;
|
|
2511
|
+
}
|
|
2512
|
+
})();
|
|
2513
|
+
const msg = errorMessageFromUniswapJsonBody(parsed) ?? (text.trim() || res.statusText);
|
|
2514
|
+
throw new Error(`List limit orders HTTP ${res.status}: ${msg}`);
|
|
2515
|
+
}
|
|
2516
|
+
return JSON.parse(text.replace(/^\uFEFF/, ""));
|
|
2517
|
+
}
|
|
2518
|
+
async function uniswapFetchLimitOrdersMcp(args) {
|
|
2519
|
+
let swapper;
|
|
2520
|
+
if ((args.swapper || "").trim()) {
|
|
2521
|
+
swapper = trimAddr3(args.swapper);
|
|
2522
|
+
} else {
|
|
2523
|
+
const keyGen = (args.keyGen || "").trim();
|
|
2524
|
+
if (!keyGen) {
|
|
2525
|
+
throw new Error("swapper or keyGen is required");
|
|
2526
|
+
}
|
|
2527
|
+
const mpc = (args.managementNodeUrl || "").trim();
|
|
2528
|
+
if (!mpc) {
|
|
2529
|
+
throw new Error("managementNodeUrl is required when swapper is not provided");
|
|
2530
|
+
}
|
|
2531
|
+
swapper = await fetchEthereumAddressForKeyGen(
|
|
2532
|
+
mpc,
|
|
2533
|
+
keyGen,
|
|
2534
|
+
args.nodeReadAuth ?? { bearerOnGet: true, jwt: null }
|
|
2535
|
+
);
|
|
2536
|
+
}
|
|
2537
|
+
return fetchUniswapXLimitOrders({
|
|
2538
|
+
swapper,
|
|
2539
|
+
chainId: args.chainId,
|
|
2540
|
+
uniswapApiKey: args.uniswapApiKey,
|
|
2541
|
+
limit: args.limit,
|
|
2542
|
+
baseUrl: args.baseUrl,
|
|
2543
|
+
fetchImpl: args.fetchImpl
|
|
2544
|
+
});
|
|
2545
|
+
}
|
|
2546
|
+
async function buildEvmMultisignBodyUniswapV4LimitOrderBatch(args) {
|
|
2547
|
+
assertUniswapLimitOrderChain(args.chainId);
|
|
2548
|
+
const permitRaw = extractPermitDataFromLimitQuote(args.fullLimitQuote);
|
|
2549
|
+
if (!permitRaw) {
|
|
2550
|
+
throw new Error(
|
|
2551
|
+
"Limit order quote has no permitData \u2014 cannot build EIP-712 sign request. Re-quote or confirm mainnet limit order support for this pair."
|
|
2552
|
+
);
|
|
2553
|
+
}
|
|
2554
|
+
const typedData = permitDataToEip712Payload(permitRaw);
|
|
2555
|
+
const submitTemplate = buildUniswapXLimitOrderSubmitBody({
|
|
2556
|
+
quoteResponse: args.fullLimitQuote,
|
|
2557
|
+
signatureHex: "0x"
|
|
2558
|
+
});
|
|
2559
|
+
return buildEip712MultisignBody({
|
|
2560
|
+
keyGen: args.keyGen,
|
|
2561
|
+
purposeText: args.purposeText,
|
|
2562
|
+
destinationChainID: String(UNISWAP_LIMIT_ORDER_CHAIN_ID),
|
|
2563
|
+
destinationAddress: PERMIT2_ADDRESS,
|
|
2564
|
+
typedData,
|
|
2565
|
+
delivery: {
|
|
2566
|
+
kind: "uniswapx_limit_order",
|
|
2567
|
+
chainId: UNISWAP_LIMIT_ORDER_CHAIN_ID,
|
|
2568
|
+
swapper: getAddress(args.swapper),
|
|
2569
|
+
submitBodyTemplate: submitTemplate,
|
|
2570
|
+
quoteResponse: args.fullLimitQuote,
|
|
2571
|
+
uniswapApiKey: args.uniswapApiKey,
|
|
2572
|
+
tradeApiBaseUrl: args.tradeApiBaseUrl ?? "https://trade-api.gateway.uniswap.org/v1"
|
|
2573
|
+
},
|
|
2574
|
+
audit: {
|
|
2575
|
+
protocol: "uniswap-v4",
|
|
2576
|
+
action: "limitOrder",
|
|
2577
|
+
routing: args.fullLimitQuote.routing ?? "LIMIT_ORDER",
|
|
2578
|
+
orderType: "Limit",
|
|
2579
|
+
primaryType: typedData.primaryType
|
|
2580
|
+
},
|
|
2581
|
+
expiryDate: args.expiryDate
|
|
2582
|
+
});
|
|
2583
|
+
}
|
|
2584
|
+
async function buildEvmMultisignBodyUniswapV4LimitOrderBatchFromMcp(args) {
|
|
2585
|
+
return buildEvmMultisignBodyUniswapV4LimitOrderBatch({
|
|
2586
|
+
keyGen: args.keyGen,
|
|
2587
|
+
chainId: args.chainId,
|
|
2588
|
+
purposeText: args.purposeText,
|
|
2589
|
+
fullLimitQuote: args.fullLimitQuote,
|
|
2590
|
+
swapper: getAddress(args.executorAddress),
|
|
2591
|
+
uniswapApiKey: args.uniswapApiKey,
|
|
2592
|
+
tradeApiBaseUrl: args.tradeApiBaseUrl,
|
|
2593
|
+
expiryDate: args.expiryDate
|
|
2594
|
+
});
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2227
2597
|
// src/protocols/evm/uniswap-v4/index.ts
|
|
2228
2598
|
var UNISWAP_V4_PROTOCOL_ID = "uniswap-v4";
|
|
2229
2599
|
var uniswapV4ProtocolModule = {
|
|
@@ -2270,6 +2640,17 @@ var uniswapV4ProtocolModule = {
|
|
|
2270
2640
|
type: { type: "EXACT_INPUT | EXACT_OUTPUT", required: true, description: "Trade type" }
|
|
2271
2641
|
}
|
|
2272
2642
|
},
|
|
2643
|
+
{
|
|
2644
|
+
id: "uniswap-v4.limit-order",
|
|
2645
|
+
protocolId: UNISWAP_V4_PROTOCOL_ID,
|
|
2646
|
+
chainCategory: "evm",
|
|
2647
|
+
description: "Place UniswapX limit order via EIP-712 sign + POST /order (Ethereum mainnet only)",
|
|
2648
|
+
commonParams: ["keyGen", "purposeText"],
|
|
2649
|
+
params: {
|
|
2650
|
+
fullLimitQuote: { type: "object", required: true, description: "Full limit order quote from Trade API" },
|
|
2651
|
+
uniswapApiKey: { type: "string", required: true, description: "Uniswap Trade API key" }
|
|
2652
|
+
}
|
|
2653
|
+
},
|
|
2273
2654
|
{
|
|
2274
2655
|
id: "uniswap-v4.mint-liquidity",
|
|
2275
2656
|
protocolId: UNISWAP_V4_PROTOCOL_ID,
|
|
@@ -2325,6 +2706,10 @@ var uniswapV4 = {
|
|
|
2325
2706
|
swapExactInput,
|
|
2326
2707
|
swapFromQuote,
|
|
2327
2708
|
buildSwapMultisignBody: buildEvmMultisignBodyUniswapV4SkipPermit2Batch,
|
|
2709
|
+
limitOrderQuote: uniswapLimitOrderQuote,
|
|
2710
|
+
buildLimitOrderMultisignBody: buildEvmMultisignBodyUniswapV4LimitOrderBatchFromMcp,
|
|
2711
|
+
fetchLimitOrders: fetchUniswapXLimitOrders,
|
|
2712
|
+
fetchLimitOrdersMcp: uniswapFetchLimitOrdersMcp,
|
|
2328
2713
|
quote: uniswapTradeQuote,
|
|
2329
2714
|
createLiquidityPosition: uniswapLpCreatePosition,
|
|
2330
2715
|
increaseLiquidityPosition: uniswapLpIncreasePosition,
|
|
@@ -2705,6 +3090,6 @@ var curveDao = {
|
|
|
2705
3090
|
registerProtocolModule(uniswapV4ProtocolModule);
|
|
2706
3091
|
registerProtocolModule(curveDaoProtocolModule);
|
|
2707
3092
|
|
|
2708
|
-
export { COINGECKO_PLATFORM_BY_CHAIN_ID, DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS, DEFI_PROTOCOLS_WITH_30MIN_EXPIRY, EIP712_SIGN_REQUEST_KIND, NEAR_CHAIN_CATEGORY, SOLANA_CHAIN_CATEGORY, approveStepsToEvmTxSteps, buildConditionalErc20ApproveSteps, buildEip712MultisignBody, buildEvmMultisignBatch, coingeckoPlatformForChainId, coreChainCategoryModule, curveDao, curveDaoProtocolModule, defiMultisignExpiryUnixSeconds, evmChainCategoryModule, finalizeMultisign, getAaveGraphqlProxyUrl, getActionsByChainCategory, getCoingeckoProxyUrl, getEulerGraphqlProxyUrl, getMapleGraphqlProxyUrl, getMorphoGraphqlProxyUrl, getProtocolModule, getProtocolModules, isEvmNativeToken, matchEvmTokenKind, mergePurposeText, nearChainCategoryModule, normalizeCurveRouterAmountString, normalizeHumanDecimalAmount, parseEvmChainIdToNumber, postJsonViaOptionalProxy, publicClientForRpc, registerProtocolModule, resolveErc20Decimals, routerSwapGasLimitFromEstimate, setAaveGraphqlProxyUrl, setCoingeckoProxyUrl, setEulerGraphqlProxyUrl, setMapleGraphqlProxyUrl, setMorphoGraphqlProxyUrl, solanaChainCategoryModule, uniswapV4, uniswapV4ProtocolModule };
|
|
3093
|
+
export { COINGECKO_PLATFORM_BY_CHAIN_ID, DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS, DEFI_PROTOCOLS_WITH_30MIN_EXPIRY, EIP712_SIGN_REQUEST_KIND, NEAR_CHAIN_CATEGORY, PAYLOAD_SIGN_ED25519_REQUEST_KIND, SOLANA_CHAIN_CATEGORY, approveStepsToEvmTxSteps, buildConditionalErc20ApproveSteps, buildEip712MultisignBody, buildEvmMultisignBatch, buildPayloadSignEd25519MultisignBody, coingeckoPlatformForChainId, coreChainCategoryModule, curveDao, curveDaoProtocolModule, defiMultisignExpiryUnixSeconds, evmChainCategoryModule, finalizeMultisign, getAaveGraphqlProxyUrl, getActionsByChainCategory, getCoingeckoProxyUrl, getEulerGraphqlProxyUrl, getMapleGraphqlProxyUrl, getMorphoGraphqlProxyUrl, getProtocolModule, getProtocolModules, isEvmNativeToken, matchEvmTokenKind, mergePurposeText, nearChainCategoryModule, normalizeCurveRouterAmountString, normalizeHumanDecimalAmount, parseEvmChainIdToNumber, postJsonViaOptionalProxy, publicClientForRpc, registerProtocolModule, resolveErc20Decimals, routerSwapGasLimitFromEstimate, setAaveGraphqlProxyUrl, setCoingeckoProxyUrl, setEulerGraphqlProxyUrl, setMapleGraphqlProxyUrl, setMorphoGraphqlProxyUrl, solanaChainCategoryModule, uniswapV4, uniswapV4ProtocolModule };
|
|
2709
3094
|
//# sourceMappingURL=index.js.map
|
|
2710
3095
|
//# sourceMappingURL=index.js.map
|