@guru-fund/sdk 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,3 +16,4 @@ export declare const V4_ZERO_ADDRESS = "0x00000000000000000000000000000000000000
16
16
  export declare const DEXSCREENER_ENDPOINT = "https://api.dexscreener.com/token-pairs/v1";
17
17
  export declare const V4_DISCOVERY_MIN_LIQUIDITY_USD = 10000;
18
18
  export declare const V4_DISCOVERY_MAX_POOLS = 3;
19
+ export declare const V4_DISCOVERY_MAX_LP_FEE = 100000;
@@ -25,3 +25,4 @@ export const V4_ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
25
25
  export const DEXSCREENER_ENDPOINT = 'https://api.dexscreener.com/token-pairs/v1';
26
26
  export const V4_DISCOVERY_MIN_LIQUIDITY_USD = 10_000;
27
27
  export const V4_DISCOVERY_MAX_POOLS = 3;
28
+ export const V4_DISCOVERY_MAX_LP_FEE = 100_000;
@@ -10,6 +10,7 @@ export interface RouterContext {
10
10
  getPath: PathFetcher;
11
11
  }
12
12
  export declare function veloraThenV4Discovery(velora: () => Promise<Route>, v4Discovery: () => Promise<Route>): Promise<Route>;
13
+ export declare function bestOfV4AndFallback(v4Discovery: () => Promise<Route>, fallback: () => Promise<Route>): Promise<Route>;
13
14
  export declare function tryWithVeloraFallback<T>(velora: () => Promise<T>, fallback: () => Promise<T>): Promise<T>;
14
15
  export declare function getRouteIn(params: RouteSearchParams, ctx: RouterContext): Promise<Route>;
15
16
  export declare function getRouteOut(params: RouteSearchParams, ctx: RouterContext): Promise<Route>;
@@ -43,6 +43,29 @@ export async function veloraThenV4Discovery(velora, v4Discovery) {
43
43
  return await v4Discovery();
44
44
  }
45
45
  }
46
+ export async function bestOfV4AndFallback(v4Discovery, fallback) {
47
+ const [v4Result, fallbackResult] = await Promise.allSettled([
48
+ v4Discovery(),
49
+ fallback(),
50
+ ]);
51
+ if (v4Result.status === 'rejected' &&
52
+ v4Result.reason instanceof Error &&
53
+ (v4Result.reason.message.includes('TOKEN_LOCKED_BY_V4_HOOK') ||
54
+ v4Result.reason.message.includes('UNISWAP_V4_HOOK_ROUTE_REVERTED'))) {
55
+ throw v4Result.reason;
56
+ }
57
+ if (v4Result.status === 'fulfilled' && fallbackResult.status === 'fulfilled') {
58
+ return BigInt(v4Result.value.data.amountToReceive) >=
59
+ BigInt(fallbackResult.value.data.amountToReceive)
60
+ ? v4Result.value
61
+ : fallbackResult.value;
62
+ }
63
+ if (v4Result.status === 'fulfilled')
64
+ return v4Result.value;
65
+ if (fallbackResult.status === 'fulfilled')
66
+ return fallbackResult.value;
67
+ throw fallbackResult.reason;
68
+ }
46
69
  export async function tryWithVeloraFallback(velora, fallback) {
47
70
  try {
48
71
  return await velora();
@@ -72,7 +95,12 @@ export async function getRouteIn(params, ctx) {
72
95
  simulator: ctx.simulator,
73
96
  getSwapFeePercentage: ctx.getSwapFeePercentage,
74
97
  };
75
- return tryWithVeloraFallback(() => veloraThenV4Discovery(() => getVeloraRoute(params, veloraCtx), () => getUniswapV4Route(params, v4Ctx)), () => getFallbackRouteIn(params, fallbackCtx));
98
+ try {
99
+ return await getVeloraRoute(params, veloraCtx);
100
+ }
101
+ catch {
102
+ return bestOfV4AndFallback(() => getUniswapV4Route(params, v4Ctx), () => getFallbackRouteIn(params, fallbackCtx));
103
+ }
76
104
  }
77
105
  export async function getRouteOut(params, ctx) {
78
106
  const veloraCtx = {
@@ -89,7 +117,12 @@ export async function getRouteOut(params, ctx) {
89
117
  simulator: ctx.simulator,
90
118
  getSwapFeePercentage: ctx.getSwapFeePercentage,
91
119
  };
92
- return tryWithVeloraFallback(() => veloraThenV4Discovery(() => getVeloraRoute(params, veloraCtx), () => getUniswapV4Route(params, v4Ctx)), () => getFallbackRouteOut(params, fallbackCtx));
120
+ try {
121
+ return await getVeloraRoute(params, veloraCtx);
122
+ }
123
+ catch {
124
+ return bestOfV4AndFallback(() => getUniswapV4Route(params, v4Ctx), () => getFallbackRouteOut(params, fallbackCtx));
125
+ }
93
126
  }
94
127
  export async function getPriceUsd1e18(token, ctx) {
95
128
  const addresses = getGuruProtocolAddresses(ctx.chainId);
@@ -8,6 +8,7 @@ export interface V4PoolKey {
8
8
  tickSpacing: number;
9
9
  hooks: string;
10
10
  }
11
+ export declare function isSafeDiscoveredV4PoolKey(key: V4PoolKey): boolean;
11
12
  export declare function computeV4PoolId(key: V4PoolKey): string;
12
13
  interface DexscreenerPair {
13
14
  dexId?: string;
@@ -1,7 +1,7 @@
1
1
  import { AbiCoder, keccak256, zeroPadValue, } from 'ethers';
2
2
  import { getGuruProtocolAddresses, } from '../addresses.js';
3
3
  import compareAddresses from '../helpers/compareAddresses.js';
4
- import { DEXSCREENER_ENDPOINT, V4_ZERO_ADDRESS, V4_DISCOVERY_MAX_POOLS, V4_DISCOVERY_MIN_LIQUIDITY_USD, VELORA_NEGATIVE_CACHE_TTL, VELORA_PATH_CACHE_TTL, } from './constants.js';
4
+ import { DEXSCREENER_ENDPOINT, V4_ZERO_ADDRESS, V4_DISCOVERY_MAX_POOLS, V4_DISCOVERY_MAX_LP_FEE, V4_DISCOVERY_MIN_LIQUIDITY_USD, VELORA_NEGATIVE_CACHE_TTL, VELORA_PATH_CACHE_TTL, } from './constants.js';
5
5
  const V4_CHAIN_CONFIG = {
6
6
  1: {
7
7
  dexscreenerSlug: 'ethereum',
@@ -20,6 +20,9 @@ const V4_CHAIN_CONFIG = {
20
20
  },
21
21
  };
22
22
  const POOL_INITIALIZE_TOPIC = '0xdd466e674ea557f56295e2d0218a125ea4b4f0f6f3307b95f85e6110838d6438';
23
+ export function isSafeDiscoveredV4PoolKey(key) {
24
+ return key.fee >= 0 && key.fee <= V4_DISCOVERY_MAX_LP_FEE;
25
+ }
23
26
  export function computeV4PoolId(key) {
24
27
  return keccak256(AbiCoder.defaultAbiCoder().encode(['address', 'address', 'uint24', 'int24', 'address'], [key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks]));
25
28
  }
@@ -150,7 +153,7 @@ async function discoverDirectV4Paths(chainId, tokenIn, tokenOut, provider, endpo
150
153
  break;
151
154
  }
152
155
  const keys = await Promise.all(poolIds.map((poolId) => resolvePoolKey(chainId, poolId, provider)));
153
- const resolvedKeys = keys.filter((key) => key !== null);
156
+ const resolvedKeys = keys.filter((key) => key !== null && isSafeDiscoveredV4PoolKey(key));
154
157
  const onchainKeys = resolvedKeys.length > 0
155
158
  ? []
156
159
  : await discoverOnchainDirectV4PoolKeys(chainId, tokenIn, tokenOut, provider);
@@ -187,7 +190,7 @@ async function discoverOnchainDirectV4PoolKeys(chainId, tokenIn, tokenOut, provi
187
190
  });
188
191
  return logs
189
192
  .map(poolKeyFromInitializeLog)
190
- .filter((key) => key !== null)
193
+ .filter((key) => key !== null && isSafeDiscoveredV4PoolKey(key))
191
194
  .sort((a, b) => a.fee - b.fee);
192
195
  }
193
196
  export function _clearV4DiscoveryCache() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guru-fund/sdk",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "Guru Protocol SDK — quote + transaction builders for on-chain managed funds.",
5
5
  "license": "MIT",
6
6
  "type": "module",