[wip] adding swap amount conversion to the swam-form
This commit is contained in:
@@ -78,10 +78,22 @@ export interface TokenDetails {
|
||||
index: number;
|
||||
}
|
||||
|
||||
export interface SwapRoute {
|
||||
poolAddress: `0x${string}`;
|
||||
inputTokenIndex: number;
|
||||
outputTokenIndex: number;
|
||||
}
|
||||
|
||||
export interface AvailableToken {
|
||||
address: `0x${string}`;
|
||||
symbol: string;
|
||||
swapRoutes: SwapRoute[];
|
||||
}
|
||||
|
||||
export function useGetPoolsByToken(tokenAddress: `0x${string}` | undefined, offset: number = 0, limit: number = 100) {
|
||||
const publicClient = usePublicClient();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [availableTokens, setAvailableTokens] = useState<`0x${string}`[] | null>(null);
|
||||
const [availableTokens, setAvailableTokens] = useState<AvailableToken[] | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
@@ -138,8 +150,10 @@ export function useGetPoolsByToken(tokenAddress: `0x${string}` | undefined, offs
|
||||
return;
|
||||
}
|
||||
|
||||
// For each pool, fetch all tokens in that pool
|
||||
const allTokensInPools: `0x${string}`[] = [];
|
||||
// Map to store available tokens with their swap routes
|
||||
const tokenRoutesMap = new Map<string, AvailableToken>();
|
||||
|
||||
// For each pool, fetch all tokens and track indices
|
||||
for (const poolAddress of poolsResult) {
|
||||
try {
|
||||
const tokensInPool = await publicClient.readContract({
|
||||
@@ -148,37 +162,62 @@ export function useGetPoolsByToken(tokenAddress: `0x${string}` | undefined, offs
|
||||
functionName: 'allTokens',
|
||||
}) as readonly `0x${string}`[];
|
||||
|
||||
// Add all tokens from this pool
|
||||
allTokensInPools.push(...tokensInPool);
|
||||
// Find the input token index in this pool
|
||||
const inputTokenIndex = tokensInPool.findIndex(
|
||||
(token) => token.toLowerCase() === tokenAddress.toLowerCase()
|
||||
);
|
||||
|
||||
if (inputTokenIndex === -1) {
|
||||
console.error('Input token not found in pool', poolAddress);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Process each token in the pool
|
||||
for (let outputTokenIndex = 0; outputTokenIndex < tokensInPool.length; outputTokenIndex++) {
|
||||
const outputTokenAddress = tokensInPool[outputTokenIndex];
|
||||
|
||||
// Skip if it's the same as the input token
|
||||
if (outputTokenIndex === inputTokenIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the symbol of this token
|
||||
const outputTokenSymbol = await publicClient.readContract({
|
||||
address: outputTokenAddress,
|
||||
abi: ERC20ABI,
|
||||
functionName: 'symbol',
|
||||
}).catch(() => null);
|
||||
|
||||
// Skip tokens with the same symbol as the selected token
|
||||
if (!outputTokenSymbol || outputTokenSymbol === selectedTokenSymbol) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create or update the available token entry
|
||||
const tokenKey = outputTokenAddress.toLowerCase();
|
||||
if (!tokenRoutesMap.has(tokenKey)) {
|
||||
tokenRoutesMap.set(tokenKey, {
|
||||
address: outputTokenAddress,
|
||||
symbol: outputTokenSymbol,
|
||||
swapRoutes: [],
|
||||
});
|
||||
}
|
||||
|
||||
// Add this swap route
|
||||
tokenRoutesMap.get(tokenKey)!.swapRoutes.push({
|
||||
poolAddress,
|
||||
inputTokenIndex,
|
||||
outputTokenIndex,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error fetching tokens from pool', poolAddress, err);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove duplicates by address
|
||||
const uniqueTokenAddresses = Array.from(new Set(allTokensInPools));
|
||||
|
||||
// Fetch symbols for all tokens and filter out those matching the selected token's symbol
|
||||
const filteredTokens: `0x${string}`[] = [];
|
||||
for (const token of uniqueTokenAddresses) {
|
||||
try {
|
||||
const tokenSymbol = await publicClient.readContract({
|
||||
address: token,
|
||||
abi: ERC20ABI,
|
||||
functionName: 'symbol',
|
||||
}).catch(() => null);
|
||||
|
||||
// Only include tokens with different symbols
|
||||
if (tokenSymbol && tokenSymbol !== selectedTokenSymbol) {
|
||||
filteredTokens.push(token);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error fetching symbol for token', token, err);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Available tokens to swap to (excluding', selectedTokenSymbol, '):', filteredTokens);
|
||||
setAvailableTokens(filteredTokens);
|
||||
const availableTokensList = Array.from(tokenRoutesMap.values());
|
||||
console.log('Available tokens with swap routes:', availableTokensList);
|
||||
setAvailableTokens(availableTokensList);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch pools and tokens');
|
||||
} finally {
|
||||
|
||||
113
src/hooks/usePartyPool.ts
Normal file
113
src/hooks/usePartyPool.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { usePublicClient } from 'wagmi';
|
||||
import IPartyPoolABI from '@/contracts/IPartyPoolABI';
|
||||
import type { AvailableToken } from './usePartyPlanner';
|
||||
|
||||
export interface SwapAmountResult {
|
||||
tokenAddress: `0x${string}`;
|
||||
tokenSymbol: string;
|
||||
amountIn: bigint;
|
||||
amountOut: bigint;
|
||||
fee: bigint;
|
||||
poolAddress: `0x${string}`;
|
||||
}
|
||||
|
||||
export function useSwapAmounts(
|
||||
availableTokens: AvailableToken[] | null,
|
||||
fromAmount: string,
|
||||
fromTokenDecimals: number
|
||||
) {
|
||||
const publicClient = usePublicClient();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [swapAmounts, setSwapAmounts] = useState<SwapAmountResult[] | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!mounted || !availableTokens || !fromAmount || parseFloat(fromAmount) <= 0) {
|
||||
setSwapAmounts(null);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const calculateSwapAmounts = async () => {
|
||||
if (!publicClient) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
|
||||
// Parse the from amount to the token's decimals
|
||||
const amountInWei = BigInt(Math.floor(parseFloat(fromAmount) * Math.pow(10, fromTokenDecimals)));
|
||||
|
||||
// Use a very large limit price (essentially no limit) - user will replace later
|
||||
// int128 max is 2^127 - 1, but we'll use a reasonable large number
|
||||
const limitPrice = BigInt('170141183460469231731687303715884105727'); // max int128
|
||||
|
||||
const results: SwapAmountResult[] = [];
|
||||
|
||||
// Calculate swap amounts for each available token using their first swap route
|
||||
for (const token of availableTokens) {
|
||||
if (token.swapRoutes.length === 0) continue;
|
||||
|
||||
// Use the first swap route for now
|
||||
const route = token.swapRoutes[0];
|
||||
|
||||
try {
|
||||
const swapResult = await publicClient.readContract({
|
||||
address: route.poolAddress,
|
||||
abi: IPartyPoolABI,
|
||||
functionName: 'swapAmounts',
|
||||
args: [
|
||||
BigInt(route.inputTokenIndex),
|
||||
BigInt(route.outputTokenIndex),
|
||||
amountInWei,
|
||||
limitPrice,
|
||||
],
|
||||
}) as readonly [bigint, bigint, bigint];
|
||||
|
||||
const [amountIn, amountOut, fee] = swapResult;
|
||||
|
||||
results.push({
|
||||
tokenAddress: token.address,
|
||||
tokenSymbol: token.symbol,
|
||||
amountIn,
|
||||
amountOut,
|
||||
fee,
|
||||
poolAddress: route.poolAddress,
|
||||
});
|
||||
|
||||
console.log(`Swap ${token.symbol}:`, {
|
||||
amountIn: amountIn.toString(),
|
||||
amountOut: amountOut.toString(),
|
||||
fee: fee.toString(),
|
||||
pool: route.poolAddress,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(`Error calculating swap for ${token.symbol}:`, err);
|
||||
}
|
||||
}
|
||||
|
||||
setSwapAmounts(results);
|
||||
} catch (err) {
|
||||
console.error('Error calculating swap amounts:', err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
calculateSwapAmounts();
|
||||
}, [publicClient, mounted, availableTokens, fromAmount, fromTokenDecimals]);
|
||||
|
||||
return {
|
||||
swapAmounts,
|
||||
loading,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user