recon-crypto-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +153 -0
  3. package/dist/abis/aave-pool.d.ts +174 -0
  4. package/dist/abis/aave-pool.js +101 -0
  5. package/dist/abis/aave-pool.js.map +1 -0
  6. package/dist/abis/aave-ui-pool-data-provider.d.ts +232 -0
  7. package/dist/abis/aave-ui-pool-data-provider.js +107 -0
  8. package/dist/abis/aave-ui-pool-data-provider.js.map +1 -0
  9. package/dist/abis/access-control.d.ts +94 -0
  10. package/dist/abis/access-control.js +51 -0
  11. package/dist/abis/access-control.js.map +1 -0
  12. package/dist/abis/compound-comet.d.ts +120 -0
  13. package/dist/abis/compound-comet.js +84 -0
  14. package/dist/abis/compound-comet.js.map +1 -0
  15. package/dist/abis/eigenlayer-delegation-manager.d.ts +23 -0
  16. package/dist/abis/eigenlayer-delegation-manager.js +18 -0
  17. package/dist/abis/eigenlayer-delegation-manager.js.map +1 -0
  18. package/dist/abis/eigenlayer-strategy-manager.d.ts +53 -0
  19. package/dist/abis/eigenlayer-strategy-manager.js +47 -0
  20. package/dist/abis/eigenlayer-strategy-manager.js.map +1 -0
  21. package/dist/abis/erc20.d.ts +78 -0
  22. package/dist/abis/erc20.js +10 -0
  23. package/dist/abis/erc20.js.map +1 -0
  24. package/dist/abis/lido.d.ts +80 -0
  25. package/dist/abis/lido.js +60 -0
  26. package/dist/abis/lido.js.map +1 -0
  27. package/dist/abis/morpho-blue.d.ts +321 -0
  28. package/dist/abis/morpho-blue.js +193 -0
  29. package/dist/abis/morpho-blue.js.map +1 -0
  30. package/dist/abis/uniswap-pool.d.ts +70 -0
  31. package/dist/abis/uniswap-pool.js +53 -0
  32. package/dist/abis/uniswap-pool.js.map +1 -0
  33. package/dist/abis/uniswap-position-manager.d.ts +71 -0
  34. package/dist/abis/uniswap-position-manager.js +41 -0
  35. package/dist/abis/uniswap-position-manager.js.map +1 -0
  36. package/dist/config/cache.d.ts +12 -0
  37. package/dist/config/cache.js +12 -0
  38. package/dist/config/cache.js.map +1 -0
  39. package/dist/config/chains.d.ts +24 -0
  40. package/dist/config/chains.js +158 -0
  41. package/dist/config/chains.js.map +1 -0
  42. package/dist/config/contracts.d.ts +107 -0
  43. package/dist/config/contracts.js +123 -0
  44. package/dist/config/contracts.js.map +1 -0
  45. package/dist/config/user-config.d.ts +15 -0
  46. package/dist/config/user-config.js +93 -0
  47. package/dist/config/user-config.js.map +1 -0
  48. package/dist/data/apis/etherscan.d.ts +30 -0
  49. package/dist/data/apis/etherscan.js +109 -0
  50. package/dist/data/apis/etherscan.js.map +1 -0
  51. package/dist/data/cache.d.ts +18 -0
  52. package/dist/data/cache.js +47 -0
  53. package/dist/data/cache.js.map +1 -0
  54. package/dist/data/format.d.ts +6 -0
  55. package/dist/data/format.js +44 -0
  56. package/dist/data/format.js.map +1 -0
  57. package/dist/data/prices.d.ts +12 -0
  58. package/dist/data/prices.js +81 -0
  59. package/dist/data/prices.js.map +1 -0
  60. package/dist/data/rpc.d.ts +17 -0
  61. package/dist/data/rpc.js +68 -0
  62. package/dist/data/rpc.js.map +1 -0
  63. package/dist/index.d.ts +2 -0
  64. package/dist/index.js +344 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/modules/balances/index.d.ts +20 -0
  67. package/dist/modules/balances/index.js +49 -0
  68. package/dist/modules/balances/index.js.map +1 -0
  69. package/dist/modules/balances/schemas.d.ts +32 -0
  70. package/dist/modules/balances/schemas.js +21 -0
  71. package/dist/modules/balances/schemas.js.map +1 -0
  72. package/dist/modules/bitcoin/index.d.ts +26 -0
  73. package/dist/modules/bitcoin/index.js +128 -0
  74. package/dist/modules/bitcoin/index.js.map +1 -0
  75. package/dist/modules/bitcoin/schemas.d.ts +49 -0
  76. package/dist/modules/bitcoin/schemas.js +51 -0
  77. package/dist/modules/bitcoin/schemas.js.map +1 -0
  78. package/dist/modules/bitcoin/send.d.ts +52 -0
  79. package/dist/modules/bitcoin/send.js +158 -0
  80. package/dist/modules/bitcoin/send.js.map +1 -0
  81. package/dist/modules/bitcoin/utxo.d.ts +99 -0
  82. package/dist/modules/bitcoin/utxo.js +116 -0
  83. package/dist/modules/bitcoin/utxo.js.map +1 -0
  84. package/dist/modules/compound/actions.d.ts +8 -0
  85. package/dist/modules/compound/actions.js +154 -0
  86. package/dist/modules/compound/actions.js.map +1 -0
  87. package/dist/modules/compound/index.d.ts +26 -0
  88. package/dist/modules/compound/index.js +141 -0
  89. package/dist/modules/compound/index.js.map +1 -0
  90. package/dist/modules/compound/schemas.d.ts +95 -0
  91. package/dist/modules/compound/schemas.js +37 -0
  92. package/dist/modules/compound/schemas.js.map +1 -0
  93. package/dist/modules/execution/index.d.ts +51 -0
  94. package/dist/modules/execution/index.js +271 -0
  95. package/dist/modules/execution/index.js.map +1 -0
  96. package/dist/modules/execution/schemas.d.ts +183 -0
  97. package/dist/modules/execution/schemas.js +88 -0
  98. package/dist/modules/execution/schemas.js.map +1 -0
  99. package/dist/modules/feedback/index.d.ts +28 -0
  100. package/dist/modules/feedback/index.js +161 -0
  101. package/dist/modules/feedback/index.js.map +1 -0
  102. package/dist/modules/feedback/rate-limit.d.ts +15 -0
  103. package/dist/modules/feedback/rate-limit.js +110 -0
  104. package/dist/modules/feedback/rate-limit.js.map +1 -0
  105. package/dist/modules/feedback/schemas.d.ts +41 -0
  106. package/dist/modules/feedback/schemas.js +40 -0
  107. package/dist/modules/feedback/schemas.js.map +1 -0
  108. package/dist/modules/morpho/actions.d.ts +8 -0
  109. package/dist/modules/morpho/actions.js +265 -0
  110. package/dist/modules/morpho/actions.js.map +1 -0
  111. package/dist/modules/morpho/index.d.ts +26 -0
  112. package/dist/modules/morpho/index.js +94 -0
  113. package/dist/modules/morpho/index.js.map +1 -0
  114. package/dist/modules/morpho/schemas.d.ts +130 -0
  115. package/dist/modules/morpho/schemas.js +34 -0
  116. package/dist/modules/morpho/schemas.js.map +1 -0
  117. package/dist/modules/portfolio/index.d.ts +3 -0
  118. package/dist/modules/portfolio/index.js +197 -0
  119. package/dist/modules/portfolio/index.js.map +1 -0
  120. package/dist/modules/portfolio/schemas.d.ts +20 -0
  121. package/dist/modules/portfolio/schemas.js +15 -0
  122. package/dist/modules/portfolio/schemas.js.map +1 -0
  123. package/dist/modules/positions/aave.d.ts +22 -0
  124. package/dist/modules/positions/aave.js +197 -0
  125. package/dist/modules/positions/aave.js.map +1 -0
  126. package/dist/modules/positions/actions.d.ts +18 -0
  127. package/dist/modules/positions/actions.js +205 -0
  128. package/dist/modules/positions/actions.js.map +1 -0
  129. package/dist/modules/positions/index.d.ts +37 -0
  130. package/dist/modules/positions/index.js +59 -0
  131. package/dist/modules/positions/index.js.map +1 -0
  132. package/dist/modules/positions/schemas.d.ts +55 -0
  133. package/dist/modules/positions/schemas.js +25 -0
  134. package/dist/modules/positions/schemas.js.map +1 -0
  135. package/dist/modules/positions/uniswap.d.ts +4 -0
  136. package/dist/modules/positions/uniswap.js +181 -0
  137. package/dist/modules/positions/uniswap.js.map +1 -0
  138. package/dist/modules/prices/index.d.ts +19 -0
  139. package/dist/modules/prices/index.js +22 -0
  140. package/dist/modules/prices/index.js.map +1 -0
  141. package/dist/modules/security/index.d.ts +26 -0
  142. package/dist/modules/security/index.js +13 -0
  143. package/dist/modules/security/index.js.map +1 -0
  144. package/dist/modules/security/permissions.d.ts +8 -0
  145. package/dist/modules/security/permissions.js +96 -0
  146. package/dist/modules/security/permissions.js.map +1 -0
  147. package/dist/modules/security/risk-score.d.ts +18 -0
  148. package/dist/modules/security/risk-score.js +116 -0
  149. package/dist/modules/security/risk-score.js.map +1 -0
  150. package/dist/modules/security/schemas.d.ts +31 -0
  151. package/dist/modules/security/schemas.js +16 -0
  152. package/dist/modules/security/schemas.js.map +1 -0
  153. package/dist/modules/security/verification.d.ts +4 -0
  154. package/dist/modules/security/verification.js +82 -0
  155. package/dist/modules/security/verification.js.map +1 -0
  156. package/dist/modules/shared/approval.d.ts +71 -0
  157. package/dist/modules/shared/approval.js +130 -0
  158. package/dist/modules/shared/approval.js.map +1 -0
  159. package/dist/modules/staking/actions.d.ts +22 -0
  160. package/dist/modules/staking/actions.js +100 -0
  161. package/dist/modules/staking/actions.js.map +1 -0
  162. package/dist/modules/staking/eigenlayer.d.ts +14 -0
  163. package/dist/modules/staking/eigenlayer.js +105 -0
  164. package/dist/modules/staking/eigenlayer.js.map +1 -0
  165. package/dist/modules/staking/index.d.ts +24 -0
  166. package/dist/modules/staking/index.js +59 -0
  167. package/dist/modules/staking/index.js.map +1 -0
  168. package/dist/modules/staking/lido.d.ts +14 -0
  169. package/dist/modules/staking/lido.js +113 -0
  170. package/dist/modules/staking/lido.js.map +1 -0
  171. package/dist/modules/staking/schemas.d.ts +34 -0
  172. package/dist/modules/staking/schemas.js +20 -0
  173. package/dist/modules/staking/schemas.js.map +1 -0
  174. package/dist/modules/swap/index.d.ts +47 -0
  175. package/dist/modules/swap/index.js +376 -0
  176. package/dist/modules/swap/index.js.map +1 -0
  177. package/dist/modules/swap/lifi.d.ts +17 -0
  178. package/dist/modules/swap/lifi.js +44 -0
  179. package/dist/modules/swap/lifi.js.map +1 -0
  180. package/dist/modules/swap/oneinch.d.ts +26 -0
  181. package/dist/modules/swap/oneinch.js +33 -0
  182. package/dist/modules/swap/oneinch.js.map +1 -0
  183. package/dist/modules/swap/schemas.d.ts +65 -0
  184. package/dist/modules/swap/schemas.js +46 -0
  185. package/dist/modules/swap/schemas.js.map +1 -0
  186. package/dist/setup.d.ts +2 -0
  187. package/dist/setup.js +257 -0
  188. package/dist/setup.js.map +1 -0
  189. package/dist/signing/pre-sign-check.d.ts +8 -0
  190. package/dist/signing/pre-sign-check.js +231 -0
  191. package/dist/signing/pre-sign-check.js.map +1 -0
  192. package/dist/signing/session.d.ts +28 -0
  193. package/dist/signing/session.js +26 -0
  194. package/dist/signing/session.js.map +1 -0
  195. package/dist/signing/tx-store.d.ts +29 -0
  196. package/dist/signing/tx-store.js +85 -0
  197. package/dist/signing/tx-store.js.map +1 -0
  198. package/dist/signing/walletconnect.d.ts +33 -0
  199. package/dist/signing/walletconnect.js +226 -0
  200. package/dist/signing/walletconnect.js.map +1 -0
  201. package/dist/types/index.d.ts +222 -0
  202. package/dist/types/index.js +18 -0
  203. package/dist/types/index.js.map +1 -0
  204. package/package.json +134 -0
@@ -0,0 +1,14 @@
1
+ import type { StakingPosition, SupportedChain } from "../../types/index.js";
2
+ /** Lido staking positions across Ethereum (stETH + wstETH) and Arbitrum (wstETH only). */
3
+ export declare function getLidoPositions(wallet: `0x${string}`, chains: SupportedChain[]): Promise<StakingPosition[]>;
4
+ /** Fetch current Lido Ethereum APR from DefiLlama yields. Cached 10 minutes. */
5
+ export declare function getLidoApr(): Promise<number | undefined>;
6
+ /**
7
+ * Rough rewards estimate for Lido — we lack historical balances without an indexer,
8
+ * so we project: rewards ≈ balance × apr × (days / 365).
9
+ */
10
+ export declare function estimateLidoRewards(currentBalance: StakingPosition, days: number): {
11
+ amount: string;
12
+ valueUsd?: number;
13
+ note: string;
14
+ } | undefined;
@@ -0,0 +1,113 @@
1
+ import { formatUnits } from "viem";
2
+ import { getClient } from "../../data/rpc.js";
3
+ import { cache } from "../../data/cache.js";
4
+ import { CACHE_TTL } from "../../config/cache.js";
5
+ import { CONTRACTS } from "../../config/contracts.js";
6
+ import { stETHAbi, wstETHAbi } from "../../abis/lido.js";
7
+ import { getTokenPrice } from "../../data/prices.js";
8
+ import { makeTokenAmount, round } from "../../data/format.js";
9
+ /** Lido staking positions across Ethereum (stETH + wstETH) and Arbitrum (wstETH only). */
10
+ export async function getLidoPositions(wallet, chains) {
11
+ const positions = [];
12
+ const ethPrice = await getTokenPrice("ethereum", "native");
13
+ for (const chain of chains) {
14
+ const client = getClient(chain);
15
+ if (chain === "ethereum") {
16
+ const stEthAddr = CONTRACTS.ethereum.lido.stETH;
17
+ const wstEthAddr = CONTRACTS.ethereum.lido.wstETH;
18
+ const [stBalance, wstBalance, stPerWst] = await client.multicall({
19
+ contracts: [
20
+ { address: stEthAddr, abi: stETHAbi, functionName: "balanceOf", args: [wallet] },
21
+ { address: wstEthAddr, abi: wstETHAbi, functionName: "balanceOf", args: [wallet] },
22
+ { address: wstEthAddr, abi: wstETHAbi, functionName: "stEthPerToken" },
23
+ ],
24
+ allowFailure: false,
25
+ });
26
+ const stEthWei = stBalance;
27
+ const wstEthWei = wstBalance;
28
+ const stPer = stPerWst;
29
+ // Convert wstETH to stETH equivalent (both 18 decimals).
30
+ const wstInStEth = (wstEthWei * stPer) / 10n ** 18n;
31
+ const totalStEthWei = stEthWei + wstInStEth;
32
+ if (totalStEthWei > 0n) {
33
+ const apr = await getLidoApr();
34
+ positions.push({
35
+ protocol: "lido",
36
+ chain,
37
+ stakedAmount: makeTokenAmount(chain, stEthAddr, totalStEthWei, 18, "stETH", ethPrice),
38
+ apr,
39
+ meta: {
40
+ stEthBalance: stEthWei.toString(),
41
+ wstEthBalance: wstEthWei.toString(),
42
+ wstEthAsStEth: wstInStEth.toString(),
43
+ },
44
+ });
45
+ }
46
+ }
47
+ if (chain === "arbitrum") {
48
+ const wstEthAddr = CONTRACTS.arbitrum.lido.wstETH;
49
+ // On Arbitrum, wstETH is the only Lido-adjacent token, and stEthPerToken
50
+ // is not available (bridged representation) — we use Ethereum's rate.
51
+ const wstBalance = (await client.readContract({
52
+ address: wstEthAddr,
53
+ abi: wstETHAbi,
54
+ functionName: "balanceOf",
55
+ args: [wallet],
56
+ }));
57
+ if (wstBalance > 0n) {
58
+ const ethClient = getClient("ethereum");
59
+ const stPer = (await ethClient.readContract({
60
+ address: CONTRACTS.ethereum.lido.wstETH,
61
+ abi: wstETHAbi,
62
+ functionName: "stEthPerToken",
63
+ }));
64
+ const wstInStEth = (wstBalance * stPer) / 10n ** 18n;
65
+ const apr = await getLidoApr();
66
+ positions.push({
67
+ protocol: "lido",
68
+ chain,
69
+ stakedAmount: makeTokenAmount(chain, wstEthAddr, wstInStEth, 18, "wstETH (as stETH)", ethPrice),
70
+ apr,
71
+ meta: { wstEthBalance: wstBalance.toString() },
72
+ });
73
+ }
74
+ }
75
+ }
76
+ return positions;
77
+ }
78
+ /** Fetch current Lido Ethereum APR from DefiLlama yields. Cached 10 minutes. */
79
+ export async function getLidoApr() {
80
+ return cache.remember("yields:lido-eth", CACHE_TTL.YIELD, async () => {
81
+ try {
82
+ const res = await fetch("https://yields.llama.fi/pools");
83
+ if (!res.ok)
84
+ return undefined;
85
+ const body = (await res.json());
86
+ const pool = body.data.find((p) => p.project === "lido" && p.symbol === "STETH" && p.chain === "Ethereum");
87
+ return pool ? round(pool.apy / 100, 6) : undefined;
88
+ }
89
+ catch {
90
+ return undefined;
91
+ }
92
+ });
93
+ }
94
+ /**
95
+ * Rough rewards estimate for Lido — we lack historical balances without an indexer,
96
+ * so we project: rewards ≈ balance × apr × (days / 365).
97
+ */
98
+ export function estimateLidoRewards(currentBalance, days) {
99
+ const apr = currentBalance.apr;
100
+ if (!apr)
101
+ return undefined;
102
+ const bal = Number(formatUnits(BigInt(currentBalance.stakedAmount.amount), 18));
103
+ const amount = bal * apr * (days / 365);
104
+ const valueUsd = currentBalance.stakedAmount.priceUsd
105
+ ? round(amount * currentBalance.stakedAmount.priceUsd, 2)
106
+ : undefined;
107
+ return {
108
+ amount: amount.toFixed(6),
109
+ valueUsd,
110
+ note: "Estimate based on current APR; actual rewards depend on rebase timing.",
111
+ };
112
+ }
113
+ //# sourceMappingURL=lido.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lido.js","sourceRoot":"","sources":["../../../src/modules/staking/lido.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ export declare const getStakingPositionsInput: z.ZodObject<{
3
+ wallet: z.ZodString;
4
+ chains: z.ZodOptional<z.ZodArray<z.ZodEnum<[string, ...string[]]>, "many">>;
5
+ }, "strip", z.ZodTypeAny, {
6
+ wallet: string;
7
+ chains?: string[] | undefined;
8
+ }, {
9
+ wallet: string;
10
+ chains?: string[] | undefined;
11
+ }>;
12
+ export declare const getStakingRewardsInput: z.ZodObject<{
13
+ wallet: z.ZodString;
14
+ period: z.ZodDefault<z.ZodOptional<z.ZodEnum<["7d", "30d", "90d", "1y"]>>>;
15
+ }, "strip", z.ZodTypeAny, {
16
+ wallet: string;
17
+ period: "7d" | "30d" | "90d" | "1y";
18
+ }, {
19
+ wallet: string;
20
+ period?: "7d" | "30d" | "90d" | "1y" | undefined;
21
+ }>;
22
+ export declare const estimateStakingYieldInput: z.ZodObject<{
23
+ protocol: z.ZodEnum<["lido", "eigenlayer"]>;
24
+ amount: z.ZodNumber;
25
+ }, "strip", z.ZodTypeAny, {
26
+ amount: number;
27
+ protocol: "lido" | "eigenlayer";
28
+ }, {
29
+ amount: number;
30
+ protocol: "lido" | "eigenlayer";
31
+ }>;
32
+ export type GetStakingPositionsArgs = z.infer<typeof getStakingPositionsInput>;
33
+ export type GetStakingRewardsArgs = z.infer<typeof getStakingRewardsInput>;
34
+ export type EstimateStakingYieldArgs = z.infer<typeof estimateStakingYieldInput>;
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ import { SUPPORTED_CHAINS } from "../../types/index.js";
3
+ const chainEnum = z.enum(SUPPORTED_CHAINS);
4
+ const walletSchema = z.string().regex(/^0x[a-fA-F0-9]{40}$/, "must be a 0x-prefixed EVM address");
5
+ export const getStakingPositionsInput = z.object({
6
+ wallet: walletSchema,
7
+ chains: z.array(chainEnum).optional(),
8
+ });
9
+ export const getStakingRewardsInput = z.object({
10
+ wallet: walletSchema,
11
+ period: z.enum(["7d", "30d", "90d", "1y"]).optional().default("30d"),
12
+ });
13
+ export const estimateStakingYieldInput = z.object({
14
+ protocol: z.enum(["lido", "eigenlayer"]),
15
+ amount: z
16
+ .number()
17
+ .positive()
18
+ .describe("Human-readable decimal amount of the staked asset (ETH for lido, LST for eigenlayer). Example: 1.5 for 1.5 ETH."),
19
+ });
20
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/modules/staking/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,gBAAoD,CAAC,CAAC;AAC/E,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,qBAAqB,EAAE,mCAAmC,CAAC,CAAC;AAElG,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE;CACtC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;CACrE,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACxC,MAAM,EAAE,CAAC;SACN,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,iHAAiH,CAClH;CACJ,CAAC,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { GetSwapQuoteArgs, PrepareSwapArgs } from "./schemas.js";
2
+ import type { SupportedChain, UnsignedTx } from "../../types/index.js";
3
+ /**
4
+ * Reject slippage configurations that are almost certainly user/agent error.
5
+ * The schema already caps at 500 bps (5%); this adds a soft-cap at 100 bps
6
+ * (1%) that requires an explicit ack. MEV sandwich bots target open-slippage
7
+ * txs, so every unnecessary basis point is paid straight to a searcher.
8
+ */
9
+ export declare function assertSlippageOk(slippageBps: number | undefined, ack: boolean | undefined): void;
10
+ export declare function getSwapQuote(args: GetSwapQuoteArgs): Promise<{
11
+ warning?: string | undefined;
12
+ savingsVsLifi?: {
13
+ source: "1inch";
14
+ outputDeltaPct: number;
15
+ outputDeltaUsd?: number;
16
+ } | undefined;
17
+ bestSource?: "1inch" | "lifi" | "tie" | undefined;
18
+ alternatives?: ({
19
+ source: "1inch";
20
+ toAmountExpected: string;
21
+ toAmountUsd?: number;
22
+ gasEstimate?: number;
23
+ } | {
24
+ source: "1inch";
25
+ error: string;
26
+ })[] | undefined;
27
+ fromChain: string;
28
+ toChain: string;
29
+ fromToken: import("@lifi/types").Token;
30
+ toToken: import("@lifi/types").Token;
31
+ fromAmount: string;
32
+ toAmountMin: string;
33
+ toAmountExpected: string;
34
+ fromAmountUsd: number | undefined;
35
+ toAmountUsd: number | undefined;
36
+ tool: string;
37
+ executionDurationSeconds: number;
38
+ feeCostsUsd: number | undefined;
39
+ gasCostsUsd: number | undefined;
40
+ crossChain: boolean;
41
+ }>;
42
+ export declare function prepareSwap(args: PrepareSwapArgs): Promise<UnsignedTx>;
43
+ export declare function getSwapStatus(args: {
44
+ txHash: string;
45
+ fromChain: SupportedChain;
46
+ toChain: SupportedChain;
47
+ }): Promise<import("@lifi/types").StatusResponse>;
@@ -0,0 +1,376 @@
1
+ import { parseUnits, formatUnits, encodeFunctionData } from "viem";
2
+ import { fetchQuote, fetchStatus } from "./lifi.js";
3
+ import { fetchOneInchQuote } from "./oneinch.js";
4
+ import { getClient } from "../../data/rpc.js";
5
+ import { erc20Abi } from "../../abis/erc20.js";
6
+ import { readUserConfig, resolveOneInchApiKey } from "../../config/user-config.js";
7
+ function sumLifiCostsUsd(items) {
8
+ if (!items || items.length === 0)
9
+ return undefined;
10
+ let total = 0;
11
+ for (const item of items) {
12
+ const stated = item.amountUSD !== undefined ? Number(item.amountUSD) : NaN;
13
+ const rawAmt = item.amount !== undefined ? Number(item.amount) : NaN;
14
+ const priceUsd = item.token?.priceUSD !== undefined ? Number(item.token.priceUSD) : NaN;
15
+ const decimals = item.token?.decimals ?? 18;
16
+ const derived = Number.isFinite(rawAmt) && Number.isFinite(priceUsd)
17
+ ? (rawAmt / 10 ** decimals) * priceUsd
18
+ : NaN;
19
+ if (Number.isFinite(derived)) {
20
+ // Both available: trust derived if they disagree wildly (stated is the known-bad
21
+ // source). 10× threshold catches the "raw-units-as-USD" class of bug.
22
+ if (Number.isFinite(stated) && derived > 0 && stated / derived > 10) {
23
+ total += derived;
24
+ }
25
+ else if (Number.isFinite(stated) && stated >= 0) {
26
+ total += stated;
27
+ }
28
+ else {
29
+ total += derived;
30
+ }
31
+ }
32
+ else if (Number.isFinite(stated) && stated >= 0) {
33
+ total += stated;
34
+ }
35
+ }
36
+ return total;
37
+ }
38
+ /** Resolve ERC-20 decimals (native = 18). */
39
+ async function resolveDecimals(chain, token, fallback) {
40
+ if (token === "native")
41
+ return 18;
42
+ if (fallback !== undefined)
43
+ return fallback;
44
+ try {
45
+ const client = getClient(chain);
46
+ const d = (await client.readContract({
47
+ address: token,
48
+ abi: erc20Abi,
49
+ functionName: "decimals",
50
+ }));
51
+ return Number(d);
52
+ }
53
+ catch {
54
+ return 18;
55
+ }
56
+ }
57
+ /**
58
+ * On-chain decimals read with no fallback path. Returns undefined for native (no
59
+ * contract to read) and undefined on RPC failure so callers can distinguish "known
60
+ * to match" from "couldn't verify". Used by prepareSwap to cross-check LiFi's
61
+ * reported token metadata before returning signable calldata.
62
+ */
63
+ async function readOnchainDecimals(chain, token) {
64
+ if (token === "native")
65
+ return undefined;
66
+ try {
67
+ const client = getClient(chain);
68
+ const d = (await client.readContract({
69
+ address: token,
70
+ abi: erc20Abi,
71
+ functionName: "decimals",
72
+ }));
73
+ return Number(d);
74
+ }
75
+ catch {
76
+ return undefined;
77
+ }
78
+ }
79
+ /**
80
+ * Reject slippage configurations that are almost certainly user/agent error.
81
+ * The schema already caps at 500 bps (5%); this adds a soft-cap at 100 bps
82
+ * (1%) that requires an explicit ack. MEV sandwich bots target open-slippage
83
+ * txs, so every unnecessary basis point is paid straight to a searcher.
84
+ */
85
+ export function assertSlippageOk(slippageBps, ack) {
86
+ if (slippageBps === undefined)
87
+ return;
88
+ if (slippageBps > 100 && !ack) {
89
+ throw new Error(`Requested slippage is ${slippageBps} bps (${(slippageBps / 100).toFixed(2)}%). ` +
90
+ `The default cap is 100 bps (1%) because anything higher is almost always a ` +
91
+ `sandwich-bait misconfiguration. If a thin-liquidity route genuinely needs this, ` +
92
+ `retry with \`acknowledgeHighSlippage: true\` and confirm with the user first.`);
93
+ }
94
+ }
95
+ export async function getSwapQuote(args) {
96
+ assertSlippageOk(args.slippageBps, args.acknowledgeHighSlippage);
97
+ const chain = args.fromChain;
98
+ const toChain = args.toChain;
99
+ const fromDecimals = await resolveDecimals(chain, args.fromToken, args.fromTokenDecimals);
100
+ const fromAmountWei = parseUnits(args.amount, fromDecimals).toString();
101
+ // Intra-chain only: 1inch has no cross-chain aggregator. Skip silently when no
102
+ // API key is configured so users without a 1inch portal account still get LiFi.
103
+ const intraChain = args.fromChain === args.toChain;
104
+ const oneInchApiKey = intraChain ? resolveOneInchApiKey(readUserConfig()) : undefined;
105
+ const [quote, oneInchRaw] = await Promise.all([
106
+ fetchQuote({
107
+ fromChain: chain,
108
+ toChain,
109
+ fromToken: args.fromToken,
110
+ toToken: args.toToken,
111
+ fromAmount: fromAmountWei,
112
+ fromAddress: args.wallet,
113
+ slippage: args.slippageBps !== undefined ? args.slippageBps / 10_000 : undefined,
114
+ }),
115
+ oneInchApiKey
116
+ ? fetchOneInchQuote({
117
+ chain,
118
+ fromToken: args.fromToken,
119
+ toToken: args.toToken,
120
+ fromAmount: fromAmountWei,
121
+ apiKey: oneInchApiKey,
122
+ }).catch((err) => ({ __error: err.message }))
123
+ : Promise.resolve(undefined),
124
+ ]);
125
+ const fromTokenDecimals = quote.action.fromToken.decimals;
126
+ const toTokenDecimals = quote.action.toToken.decimals;
127
+ const fromPriceUsd = Number(quote.action.fromToken.priceUSD ?? NaN);
128
+ const toPriceUsd = Number(quote.action.toToken.priceUSD ?? NaN);
129
+ const fromAmountFormatted = formatUnits(BigInt(quote.action.fromAmount), fromTokenDecimals);
130
+ const rawToAmount = formatUnits(BigInt(quote.estimate.toAmount), toTokenDecimals);
131
+ const rawToAmountMin = formatUnits(BigInt(quote.estimate.toAmountMin), toTokenDecimals);
132
+ const fromAmountUsd = Number.isFinite(fromPriceUsd)
133
+ ? Number(fromAmountFormatted) * fromPriceUsd
134
+ : undefined;
135
+ const statedToAmountUsd = Number.isFinite(toPriceUsd)
136
+ ? Number(rawToAmount) * toPriceUsd
137
+ : undefined;
138
+ // Sanity-check the output amount. LiFi has been observed returning toAmount scaled
139
+ // wrong for some aggregator integrations (100 USDC → supposedly 1288 WBTC). When
140
+ // priced out, the implied output USD vastly exceeds the input USD — no rational
141
+ // route pays >10× the input. When that happens, we re-derive the displayed amount
142
+ // from prices and attach a warning so the caller doesn't sign a malformed tx.
143
+ let toAmountExpected = rawToAmount;
144
+ let toAmountMin = rawToAmountMin;
145
+ let toAmountUsd = statedToAmountUsd;
146
+ let warning;
147
+ if (fromAmountUsd !== undefined &&
148
+ statedToAmountUsd !== undefined &&
149
+ fromAmountUsd > 0 &&
150
+ statedToAmountUsd / fromAmountUsd > 10) {
151
+ // Derive what the output *should* be from prices.
152
+ const impliedToAmount = fromAmountUsd / toPriceUsd;
153
+ // Preserve the route's stated slippage ratio when re-deriving the min.
154
+ const rawRatio = Number(rawToAmount) > 0 ? Number(rawToAmountMin) / Number(rawToAmount) : 1;
155
+ toAmountExpected = impliedToAmount.toString();
156
+ toAmountMin = (impliedToAmount * rawRatio).toString();
157
+ toAmountUsd = fromAmountUsd;
158
+ warning =
159
+ `LiFi returned toAmount=${rawToAmount} ${quote.action.toToken.symbol} (~$${statedToAmountUsd.toFixed(2)}) ` +
160
+ `which is >10× the input value ($${fromAmountUsd.toFixed(2)}). Displayed output re-derived from ` +
161
+ `token prices. Do NOT sign a prepared tx using this quote — fetch a fresh one.`;
162
+ }
163
+ // Intra-chain comparison against 1inch. Quote in the same token, so a direct
164
+ // numeric comparison of output amounts is meaningful. USD is derived from the
165
+ // LiFi-provided toToken price (1inch doesn't return priceUSD) so both sides
166
+ // use the same reference price and only the route differs.
167
+ let alternatives;
168
+ let bestSource;
169
+ let savingsVsLifi;
170
+ if (intraChain && oneInchRaw) {
171
+ if ("__error" in oneInchRaw) {
172
+ alternatives = [{ source: "1inch", error: oneInchRaw.__error }];
173
+ }
174
+ else {
175
+ const oiDecimals = oneInchRaw.dstToken?.decimals ?? toTokenDecimals;
176
+ const oiFormatted = formatUnits(BigInt(oneInchRaw.dstAmount), oiDecimals);
177
+ const oiOut = Number(oiFormatted);
178
+ const oiUsd = Number.isFinite(toPriceUsd) ? oiOut * toPriceUsd : undefined;
179
+ alternatives = [
180
+ {
181
+ source: "1inch",
182
+ toAmountExpected: oiFormatted,
183
+ toAmountUsd: oiUsd,
184
+ gasEstimate: oneInchRaw.gas,
185
+ },
186
+ ];
187
+ // Compare against the *raw* LiFi toAmount (not the re-derived one). If LiFi's
188
+ // quote was flagged by the >10× sanity check, the raw number is the one the
189
+ // aggregator actually advertised — that's what we're comparing route quality on.
190
+ const lifiOut = Number(rawToAmount);
191
+ if (lifiOut > 0 && oiOut > 0) {
192
+ const delta = (oiOut - lifiOut) / lifiOut;
193
+ if (Math.abs(delta) < 0.0005)
194
+ bestSource = "tie";
195
+ else
196
+ bestSource = delta > 0 ? "1inch" : "lifi";
197
+ savingsVsLifi = {
198
+ source: "1inch",
199
+ outputDeltaPct: delta * 100,
200
+ outputDeltaUsd: Number.isFinite(toPriceUsd) ? (oiOut - lifiOut) * toPriceUsd : undefined,
201
+ };
202
+ }
203
+ }
204
+ }
205
+ return {
206
+ fromChain: args.fromChain,
207
+ toChain: args.toChain,
208
+ fromToken: quote.action.fromToken,
209
+ toToken: quote.action.toToken,
210
+ fromAmount: fromAmountFormatted,
211
+ toAmountMin,
212
+ toAmountExpected,
213
+ fromAmountUsd,
214
+ toAmountUsd,
215
+ tool: quote.tool,
216
+ executionDurationSeconds: quote.estimate.executionDuration,
217
+ feeCostsUsd: sumLifiCostsUsd(quote.estimate.feeCosts),
218
+ gasCostsUsd: sumLifiCostsUsd(quote.estimate.gasCosts),
219
+ crossChain: args.fromChain !== args.toChain,
220
+ ...(alternatives ? { alternatives } : {}),
221
+ ...(bestSource ? { bestSource } : {}),
222
+ ...(savingsVsLifi ? { savingsVsLifi } : {}),
223
+ ...(warning ? { warning } : {}),
224
+ };
225
+ }
226
+ export async function prepareSwap(args) {
227
+ assertSlippageOk(args.slippageBps, args.acknowledgeHighSlippage);
228
+ const chain = args.fromChain;
229
+ const fromDecimals = await resolveDecimals(chain, args.fromToken, args.fromTokenDecimals);
230
+ const fromAmountWei = parseUnits(args.amount, fromDecimals).toString();
231
+ const quote = await fetchQuote({
232
+ fromChain: chain,
233
+ toChain: args.toChain,
234
+ fromToken: args.fromToken,
235
+ toToken: args.toToken,
236
+ fromAmount: fromAmountWei,
237
+ fromAddress: args.wallet,
238
+ slippage: args.slippageBps !== undefined ? args.slippageBps / 10_000 : undefined,
239
+ });
240
+ const txRequest = quote.transactionRequest;
241
+ if (!txRequest || !txRequest.to || !txRequest.data) {
242
+ throw new Error("LiFi did not return a transactionRequest for this quote.");
243
+ }
244
+ // Cross-check LiFi's reported token decimals against on-chain reads. A mismatch
245
+ // would mean either LiFi has stale metadata or the route targets a token different
246
+ // from what we asked for — in either case, the formatted expectedOut/minOut shown
247
+ // to the user would be wrong, so refuse. Native assets are skipped (no contract).
248
+ const fromToken = args.fromToken;
249
+ const toToken = args.toToken;
250
+ const [fromDecimalsOnchain, toDecimalsOnchain] = await Promise.all([
251
+ readOnchainDecimals(chain, fromToken),
252
+ readOnchainDecimals(args.toChain, toToken),
253
+ ]);
254
+ if (fromDecimalsOnchain !== undefined &&
255
+ fromDecimalsOnchain !== quote.action.fromToken.decimals) {
256
+ throw new Error(`Decimals mismatch for fromToken ${quote.action.fromToken.symbol} (${quote.action.fromToken.address}): ` +
257
+ `LiFi reports ${quote.action.fromToken.decimals}, on-chain says ${fromDecimalsOnchain}. ` +
258
+ `Refusing to return calldata.`);
259
+ }
260
+ if (toDecimalsOnchain !== undefined &&
261
+ toDecimalsOnchain !== quote.action.toToken.decimals) {
262
+ throw new Error(`Decimals mismatch for toToken ${quote.action.toToken.symbol} (${quote.action.toToken.address}): ` +
263
+ `LiFi reports ${quote.action.toToken.decimals}, on-chain says ${toDecimalsOnchain}. ` +
264
+ `Refusing to return calldata.`);
265
+ }
266
+ // Sanity-check the quote before returning signable calldata. LiFi has been observed
267
+ // returning toAmount scaled wrong on certain aggregator integrations (e.g. 10 USDC →
268
+ // ~4500 ETH). The calldata embeds the bogus minOut and won't execute, but we refuse
269
+ // up front so the user doesn't waste a signature on a broken quote. Mirrors the
270
+ // warning path in getSwapQuote.
271
+ const fromPriceUsd = Number(quote.action.fromToken.priceUSD ?? NaN);
272
+ const toPriceUsd = Number(quote.action.toToken.priceUSD ?? NaN);
273
+ const fromAmountFormatted = Number(formatUnits(BigInt(quote.action.fromAmount), quote.action.fromToken.decimals));
274
+ const toAmountFormatted = Number(formatUnits(BigInt(quote.estimate.toAmount), quote.action.toToken.decimals));
275
+ if (Number.isFinite(fromPriceUsd) &&
276
+ Number.isFinite(toPriceUsd) &&
277
+ fromPriceUsd > 0 &&
278
+ toPriceUsd > 0) {
279
+ const fromUsd = fromAmountFormatted * fromPriceUsd;
280
+ const toUsd = toAmountFormatted * toPriceUsd;
281
+ if (fromUsd > 0 && toUsd / fromUsd > 10) {
282
+ throw new Error(`LiFi returned a malformed quote: toAmount=${toAmountFormatted} ${quote.action.toToken.symbol} ` +
283
+ `(~$${toUsd.toFixed(2)}) for input ~$${fromUsd.toFixed(2)} (route: ${quote.tool}). ` +
284
+ `Output is >10× the input value, so the calldata is not safe to sign. ` +
285
+ `Re-run get_swap_quote to fetch a fresh route.`);
286
+ }
287
+ }
288
+ const fromSym = quote.action.fromToken.symbol;
289
+ const toSym = quote.action.toToken.symbol;
290
+ const crossChain = args.fromChain !== args.toChain;
291
+ const description = crossChain
292
+ ? `Bridge ${args.amount} ${fromSym} from ${args.fromChain} to ${toSym} on ${args.toChain} via ${quote.tool}`
293
+ : `Swap ${args.amount} ${fromSym} → ${toSym} on ${args.fromChain} via ${quote.tool}`;
294
+ const swapTx = {
295
+ chain,
296
+ to: txRequest.to,
297
+ data: txRequest.data,
298
+ value: txRequest.value ? BigInt(txRequest.value).toString() : "0",
299
+ from: args.wallet,
300
+ description,
301
+ decoded: {
302
+ functionName: "lifi",
303
+ args: {
304
+ tool: quote.tool,
305
+ from: `${args.amount} ${fromSym}`,
306
+ expectedOut: `${formatUnits(BigInt(quote.estimate.toAmount), quote.action.toToken.decimals)} ${toSym}`,
307
+ minOut: `${formatUnits(BigInt(quote.estimate.toAmountMin), quote.action.toToken.decimals)} ${toSym}`,
308
+ },
309
+ },
310
+ gasEstimate: txRequest.gasLimit ? BigInt(txRequest.gasLimit).toString() : undefined,
311
+ };
312
+ // ERC-20 inputs require an allowance on `approvalAddress` (LiFi Diamond for most
313
+ // routes, but some tools use a different executor). Without this, the swap reverts
314
+ // on the Diamond's transferFrom — Ledger Live shows "Continue" disabled with $0
315
+ // estimated cost because eth_estimateGas fails. Native inputs skip this step.
316
+ if (fromToken !== "native") {
317
+ const approvalAddress = (quote.estimate.approvalAddress ??
318
+ txRequest.to);
319
+ const client = getClient(chain);
320
+ const allowance = (await client.readContract({
321
+ address: fromToken,
322
+ abi: erc20Abi,
323
+ functionName: "allowance",
324
+ args: [args.wallet, approvalAddress],
325
+ }));
326
+ const amountWeiBig = BigInt(fromAmountWei);
327
+ if (allowance < amountWeiBig) {
328
+ const approveTx = {
329
+ chain,
330
+ to: fromToken,
331
+ data: encodeFunctionData({
332
+ abi: erc20Abi,
333
+ functionName: "approve",
334
+ args: [approvalAddress, amountWeiBig],
335
+ }),
336
+ value: "0",
337
+ from: args.wallet,
338
+ description: `Approve ${args.amount} ${fromSym} for ${quote.tool} via LiFi (exact amount)`,
339
+ decoded: {
340
+ functionName: "approve",
341
+ args: { spender: approvalAddress, amount: `${args.amount} ${fromSym}` },
342
+ },
343
+ next: swapTx,
344
+ };
345
+ if (allowance > 0n) {
346
+ // USDT-style reset: tokens like USDT revert on approve(nonzero→nonzero).
347
+ // Chain approve(0) → approve(amount) → swap so we don't silently fail on
348
+ // the first tx of the triple.
349
+ const resetTx = {
350
+ chain,
351
+ to: fromToken,
352
+ data: encodeFunctionData({
353
+ abi: erc20Abi,
354
+ functionName: "approve",
355
+ args: [approvalAddress, 0n],
356
+ }),
357
+ value: "0",
358
+ from: args.wallet,
359
+ description: `Reset ${fromSym} allowance to 0 (required by USDT-style tokens before re-approval)`,
360
+ decoded: {
361
+ functionName: "approve",
362
+ args: { spender: approvalAddress, amount: "0" },
363
+ },
364
+ next: approveTx,
365
+ };
366
+ return resetTx;
367
+ }
368
+ return approveTx;
369
+ }
370
+ }
371
+ return swapTx;
372
+ }
373
+ export async function getSwapStatus(args) {
374
+ return fetchStatus(args.txHash, args.fromChain, args.toChain);
375
+ }
376
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/swap/index.ts"],"names":[],"mappings":"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"}