@0xprotovox/deficlaw 0.6.0 → 0.6.1
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.
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
declare const SOL_MINT = "So11111111111111111111111111111111111111112";
|
|
2
|
-
declare const SOL_DECIMALS = 9;
|
|
3
|
-
export interface JupiterQuote {
|
|
4
|
-
inputMint: string;
|
|
5
|
-
outputMint: string;
|
|
6
|
-
inAmount: string;
|
|
7
|
-
outAmount: string;
|
|
8
|
-
otherAmountThreshold: string;
|
|
9
|
-
priceImpactPct: string;
|
|
10
|
-
slippageBps: number;
|
|
11
|
-
routePlan: {
|
|
12
|
-
swapInfo: {
|
|
13
|
-
ammKey: string;
|
|
14
|
-
label: string;
|
|
15
|
-
};
|
|
16
|
-
}[];
|
|
17
|
-
}
|
|
18
1
|
export interface SlippageEstimate {
|
|
19
2
|
buyAmountUsd: number;
|
|
20
|
-
inputLamports: string;
|
|
21
3
|
estimatedOutput: number;
|
|
22
4
|
priceImpactPct: number;
|
|
23
5
|
effectivePrice: number;
|
|
@@ -25,13 +7,8 @@ export interface SlippageEstimate {
|
|
|
25
7
|
route: string;
|
|
26
8
|
}
|
|
27
9
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
|
|
31
|
-
export declare function getQuote(outputMint: string, amountLamports: string, slippageBps?: number): Promise<JupiterQuote | null>;
|
|
32
|
-
/**
|
|
33
|
-
* Estimate slippage for multiple buy sizes.
|
|
34
|
-
* Returns quotes for $50, $100, $500, $1000 buys.
|
|
10
|
+
* Estimate slippage from pool liquidity using constant-product AMM formula.
|
|
11
|
+
* priceImpact ≈ tradeSize / (2 * liquidityUsd) * 100
|
|
12
|
+
* This is an approximation — real slippage depends on pool type and route.
|
|
35
13
|
*/
|
|
36
|
-
export declare function
|
|
37
|
-
export { SOL_MINT, SOL_DECIMALS };
|
|
14
|
+
export declare function estimateSlippageFromLiquidity(tokenPriceUsd: number, liquidityUsd: number, dex: string, buyAmounts?: number[]): SlippageEstimate[];
|
package/dist/sources/jupiter.js
CHANGED
|
@@ -1,82 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Slippage Estimation — based on DexScreener liquidity data
|
|
3
|
+
* Jupiter API now requires auth, so we calculate price impact from pool liquidity
|
|
4
|
+
* Formula: priceImpact ≈ tradeSize / (2 * poolLiquidity) for constant-product AMMs
|
|
5
5
|
*/
|
|
6
|
-
import { MemoryCache } from '../cache/memoryCache.js';
|
|
7
6
|
import { debug } from '../utils/debug.js';
|
|
8
|
-
const BASE_URL = 'https://api.jup.ag/quote/v1';
|
|
9
|
-
const CACHE_TTL = 30_000; // 30s cache for quotes
|
|
10
|
-
const SOL_MINT = 'So11111111111111111111111111111111111111112';
|
|
11
|
-
const SOL_DECIMALS = 9;
|
|
12
|
-
const quoteCache = new MemoryCache(CACHE_TTL);
|
|
13
7
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
8
|
+
* Estimate slippage from pool liquidity using constant-product AMM formula.
|
|
9
|
+
* priceImpact ≈ tradeSize / (2 * liquidityUsd) * 100
|
|
10
|
+
* This is an approximation — real slippage depends on pool type and route.
|
|
16
11
|
*/
|
|
17
|
-
export
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
return null;
|
|
35
|
-
quoteCache.set(cacheKey, data);
|
|
36
|
-
return data;
|
|
37
|
-
}
|
|
38
|
-
catch (err) {
|
|
39
|
-
debug(`Jupiter quote failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Estimate slippage for multiple buy sizes.
|
|
45
|
-
* Returns quotes for $50, $100, $500, $1000 buys.
|
|
46
|
-
*/
|
|
47
|
-
export async function estimateSlippage(tokenMint, solPriceUsd, tokenDecimals) {
|
|
48
|
-
const buyAmounts = [50, 100, 500, 1000]; // USD amounts
|
|
49
|
-
const results = [];
|
|
50
|
-
// Convert USD amounts to SOL lamports
|
|
51
|
-
const quotes = await Promise.all(buyAmounts.map(async (usdAmount) => {
|
|
52
|
-
const solAmount = usdAmount / solPriceUsd;
|
|
53
|
-
const lamports = Math.round(solAmount * 1e9).toString();
|
|
54
|
-
const quote = await getQuote(tokenMint, lamports);
|
|
55
|
-
if (!quote)
|
|
56
|
-
return null;
|
|
57
|
-
const outAmount = parseFloat(quote.outAmount) / Math.pow(10, tokenDecimals);
|
|
58
|
-
const priceImpact = parseFloat(quote.priceImpactPct) || 0;
|
|
59
|
-
const effectivePrice = outAmount > 0 ? usdAmount / outAmount : 0;
|
|
60
|
-
// Determine route label
|
|
61
|
-
const routeLabels = quote.routePlan
|
|
62
|
-
?.map(r => r.swapInfo?.label)
|
|
63
|
-
.filter(Boolean) ?? [];
|
|
64
|
-
const route = routeLabels.length > 0 ? routeLabels.join(' -> ') : 'unknown';
|
|
12
|
+
export function estimateSlippageFromLiquidity(tokenPriceUsd, liquidityUsd, dex, buyAmounts = [50, 100, 500, 1000]) {
|
|
13
|
+
if (liquidityUsd <= 0 || tokenPriceUsd <= 0)
|
|
14
|
+
return [];
|
|
15
|
+
return buyAmounts.map(usdAmount => {
|
|
16
|
+
// Constant-product AMM price impact formula
|
|
17
|
+
// For a buy of size X into a pool of size L:
|
|
18
|
+
// priceImpact ≈ X / (2 * L) for small trades
|
|
19
|
+
// For larger trades relative to pool: priceImpact = X / (L + X)
|
|
20
|
+
const impact = usdAmount / (liquidityUsd + usdAmount);
|
|
21
|
+
const impactPct = impact * 100;
|
|
22
|
+
// Effective price after slippage
|
|
23
|
+
const effectivePrice = tokenPriceUsd * (1 + impact);
|
|
24
|
+
// Estimated tokens received
|
|
25
|
+
const estimatedOutput = usdAmount / effectivePrice;
|
|
26
|
+
// Convert impact to basis points
|
|
27
|
+
const slippageBps = Math.round(impactPct * 100);
|
|
28
|
+
debug(`Slippage $${usdAmount}: impact ${impactPct.toFixed(4)}% (${slippageBps}bps) on ${dex}`);
|
|
65
29
|
return {
|
|
66
30
|
buyAmountUsd: usdAmount,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
priceImpactPct: Math.round(priceImpact * 10000) / 10000,
|
|
31
|
+
estimatedOutput: Math.round(estimatedOutput * 1000000) / 1000000,
|
|
32
|
+
priceImpactPct: Math.round(impactPct * 10000) / 10000,
|
|
70
33
|
effectivePrice,
|
|
71
|
-
slippageBps
|
|
72
|
-
route,
|
|
34
|
+
slippageBps,
|
|
35
|
+
route: dex,
|
|
73
36
|
};
|
|
74
|
-
})
|
|
75
|
-
for (const q of quotes) {
|
|
76
|
-
if (q)
|
|
77
|
-
results.push(q);
|
|
78
|
-
}
|
|
79
|
-
return results;
|
|
37
|
+
});
|
|
80
38
|
}
|
|
81
|
-
export { SOL_MINT, SOL_DECIMALS };
|
|
82
39
|
//# sourceMappingURL=jupiter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jupiter.js","sourceRoot":"","sources":["../../src/sources/jupiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"jupiter.js","sourceRoot":"","sources":["../../src/sources/jupiter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAW1C;;;;GAIG;AACH,MAAM,UAAU,6BAA6B,CAC3C,aAAqB,EACrB,YAAoB,EACpB,GAAW,EACX,aAAuB,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC;IAE3C,IAAI,YAAY,IAAI,CAAC,IAAI,aAAa,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAEvD,OAAO,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;QAChC,4CAA4C;QAC5C,6CAA6C;QAC7C,6CAA6C;QAC7C,gEAAgE;QAChE,MAAM,MAAM,GAAG,SAAS,GAAG,CAAC,YAAY,GAAG,SAAS,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,MAAM,GAAG,GAAG,CAAC;QAE/B,iCAAiC;QACjC,MAAM,cAAc,GAAG,aAAa,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;QAEpD,4BAA4B;QAC5B,MAAM,eAAe,GAAG,SAAS,GAAG,cAAc,CAAC;QAEnD,iCAAiC;QACjC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC;QAEhD,KAAK,CAAC,aAAa,SAAS,YAAY,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,WAAW,WAAW,GAAG,EAAE,CAAC,CAAC;QAE/F,OAAO;YACL,YAAY,EAAE,SAAS;YACvB,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,eAAe,GAAG,OAAO,CAAC,GAAG,OAAO;YAChE,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,GAAG,KAAK;YACrD,cAAc;YACd,WAAW;YACX,KAAK,EAAE,GAAG;SACX,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* estimate_slippage tool —
|
|
3
|
-
*
|
|
4
|
-
* Uses Jupiter Quote API (free, no auth).
|
|
2
|
+
* estimate_slippage tool — Liquidity-based slippage estimation
|
|
3
|
+
* Uses DexScreener pool data to estimate price impact at $50/$100/$500/$1000
|
|
5
4
|
*/
|
|
6
5
|
import { type SlippageEstimate } from '../sources/jupiter.js';
|
|
7
6
|
interface SlippageResult {
|
|
@@ -9,7 +8,8 @@ interface SlippageResult {
|
|
|
9
8
|
symbol: string;
|
|
10
9
|
name: string;
|
|
11
10
|
currentPriceUsd: number;
|
|
12
|
-
|
|
11
|
+
liquidityUsd: number;
|
|
12
|
+
dex: string;
|
|
13
13
|
estimates: SlippageEstimate[];
|
|
14
14
|
summary: string;
|
|
15
15
|
fetchedAt: string;
|
|
@@ -1,69 +1,71 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* estimate_slippage tool —
|
|
3
|
-
*
|
|
4
|
-
* Uses Jupiter Quote API (free, no auth).
|
|
2
|
+
* estimate_slippage tool — Liquidity-based slippage estimation
|
|
3
|
+
* Uses DexScreener pool data to estimate price impact at $50/$100/$500/$1000
|
|
5
4
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { getTokenSecurity } from '../sources/solanaRpc.js';
|
|
9
|
-
import { debug } from '../utils/debug.js';
|
|
10
|
-
const SOL_MINT = 'So11111111111111111111111111111111111111112';
|
|
5
|
+
import { estimateSlippageFromLiquidity } from '../sources/jupiter.js';
|
|
6
|
+
import { getTokenPair } from '../sources/dexscreener.js';
|
|
11
7
|
export async function handleEstimateSlippage(args) {
|
|
12
8
|
if (!args.address || args.address.trim().length === 0) {
|
|
13
9
|
return { error: 'Token address is required. Provide a Solana token mint address.' };
|
|
14
10
|
}
|
|
15
11
|
const address = args.address.trim();
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (!solPrice) {
|
|
20
|
-
return { error: 'Could not fetch SOL price. DexScreener may be temporarily unavailable.' };
|
|
12
|
+
const pair = await getTokenPair(address, 'solana');
|
|
13
|
+
if (!pair) {
|
|
14
|
+
return { error: `Token not found on DexScreener: ${address}. Check the address or try searching by name.` };
|
|
21
15
|
}
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
const priceUsd = parseFloat(pair.priceUsd) || 0;
|
|
17
|
+
const liquidityUsd = pair.liquidity?.usd || 0;
|
|
18
|
+
const symbol = pair.baseToken.symbol;
|
|
19
|
+
const name = pair.baseToken.name;
|
|
20
|
+
const dex = pair.dexId;
|
|
21
|
+
if (liquidityUsd <= 0) {
|
|
22
|
+
return { error: `No liquidity data for ${symbol}. Cannot estimate slippage.` };
|
|
26
23
|
}
|
|
27
|
-
|
|
28
|
-
const security = await getTokenSecurity(address).catch(() => null);
|
|
29
|
-
const tokenDecimals = security?.decimals ?? 6;
|
|
30
|
-
const estimates = await estimateSlippage(address, solPrice.priceUsd, tokenDecimals);
|
|
24
|
+
const estimates = estimateSlippageFromLiquidity(priceUsd, liquidityUsd, dex);
|
|
31
25
|
if (estimates.length === 0) {
|
|
32
|
-
return { error: `
|
|
26
|
+
return { error: `Could not estimate slippage for ${symbol}.` };
|
|
33
27
|
}
|
|
34
28
|
// Build summary
|
|
35
|
-
const
|
|
36
|
-
|
|
29
|
+
const lines = [];
|
|
30
|
+
lines.push(`Slippage estimates for ${symbol} (${name}):`);
|
|
31
|
+
lines.push(`Pool liquidity: $${liquidityUsd.toLocaleString()} on ${dex}`);
|
|
32
|
+
lines.push('');
|
|
37
33
|
for (const est of estimates) {
|
|
38
|
-
const impactStr = est.priceImpactPct >
|
|
39
|
-
? `${est.priceImpactPct.toFixed(2)}% (HIGH)`
|
|
40
|
-
: est.priceImpactPct >
|
|
41
|
-
? `${est.priceImpactPct.toFixed(2)}% (
|
|
42
|
-
:
|
|
43
|
-
|
|
34
|
+
const impactStr = est.priceImpactPct > 5
|
|
35
|
+
? `${est.priceImpactPct.toFixed(2)}% (VERY HIGH)`
|
|
36
|
+
: est.priceImpactPct > 1
|
|
37
|
+
? `${est.priceImpactPct.toFixed(2)}% (HIGH)`
|
|
38
|
+
: est.priceImpactPct > 0.3
|
|
39
|
+
? `${est.priceImpactPct.toFixed(3)}% (moderate)`
|
|
40
|
+
: `${est.priceImpactPct.toFixed(4)}% (low)`;
|
|
41
|
+
lines.push(` $${est.buyAmountUsd}: ~${est.estimatedOutput.toLocaleString()} ${symbol}, price impact ${impactStr}`);
|
|
44
42
|
}
|
|
45
43
|
// Overall assessment
|
|
46
44
|
const maxImpact = Math.max(...estimates.map(e => e.priceImpactPct));
|
|
45
|
+
lines.push('');
|
|
47
46
|
if (maxImpact > 5) {
|
|
48
|
-
|
|
47
|
+
lines.push('WARNING: Very high price impact. Extremely illiquid token. Trade tiny amounts only.');
|
|
49
48
|
}
|
|
50
49
|
else if (maxImpact > 2) {
|
|
51
|
-
|
|
50
|
+
lines.push('Caution: Significant price impact at larger sizes. Trade in smaller amounts.');
|
|
52
51
|
}
|
|
53
52
|
else if (maxImpact > 0.5) {
|
|
54
|
-
|
|
53
|
+
lines.push('Moderate liquidity. $100-500 buys are reasonable, larger sizes will move the price.');
|
|
55
54
|
}
|
|
56
55
|
else {
|
|
57
|
-
|
|
56
|
+
lines.push('Good liquidity. All tested buy sizes have low price impact.');
|
|
58
57
|
}
|
|
58
|
+
lines.push('');
|
|
59
|
+
lines.push('(Estimated from pool liquidity using constant-product AMM formula. Actual slippage may vary by DEX and route.)');
|
|
59
60
|
return {
|
|
60
61
|
token: address,
|
|
61
|
-
symbol
|
|
62
|
-
name
|
|
63
|
-
currentPriceUsd:
|
|
64
|
-
|
|
62
|
+
symbol,
|
|
63
|
+
name,
|
|
64
|
+
currentPriceUsd: priceUsd,
|
|
65
|
+
liquidityUsd,
|
|
66
|
+
dex,
|
|
65
67
|
estimates,
|
|
66
|
-
summary:
|
|
68
|
+
summary: lines.join('\n'),
|
|
67
69
|
fetchedAt: new Date().toISOString(),
|
|
68
70
|
};
|
|
69
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"estimateSlippage.js","sourceRoot":"","sources":["../../src/tools/estimateSlippage.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"estimateSlippage.js","sourceRoot":"","sources":["../../src/tools/estimateSlippage.ts"],"names":[],"mappings":"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"}
|