adding a stake form and approvals in both stake and swap form
This commit is contained in:
@@ -5,6 +5,7 @@ import { usePublicClient } from 'wagmi';
|
||||
import chainInfo from '@/contracts/liqp-deployments.json';
|
||||
import IPartyPlannerABI from '@/contracts/IPartyPlannerABI';
|
||||
import IPartyPoolABI from '@/contracts/IPartyPoolABI';
|
||||
import IPartyPoolViewerABI from '@/contracts/IPartyPoolViewerABI';
|
||||
import { ERC20ABI } from '@/contracts/ERC20ABI';
|
||||
|
||||
export function useGetAllTokens(offset: number = 0, limit: number = 100) {
|
||||
@@ -324,4 +325,201 @@ export function useTokenDetails(userAddress: `0x${string}` | undefined) {
|
||||
loading,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export interface PoolDetails {
|
||||
address: `0x${string}`;
|
||||
name: string;
|
||||
symbol: string;
|
||||
tokens: readonly `0x${string}`[];
|
||||
}
|
||||
|
||||
export function useGetAllPools(offset: number = 0, limit: number = 100) {
|
||||
const publicClient = usePublicClient();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [pools, setPools] = useState<readonly `0x${string}`[] | null>(null);
|
||||
const [poolDetails, setPoolDetails] = useState<PoolDetails[] | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// Handle hydration for Next.js static export
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!mounted) return;
|
||||
|
||||
const fetchPools = async () => {
|
||||
if (!publicClient) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
// Get chain ID and contract address
|
||||
const chainId = await publicClient.getChainId();
|
||||
const address = (chainInfo as Record<string, { v1: { PartyPlanner: string; PartyPoolViewer: string } }>)[chainId.toString()]?.v1?.PartyPlanner;
|
||||
|
||||
if (!address) {
|
||||
setError('IPartyPlanner contract not found for current chain');
|
||||
setPools([]);
|
||||
setPoolDetails([]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Call getAllPools function
|
||||
const result = await publicClient.readContract({
|
||||
address: address as `0x${string}`,
|
||||
abi: IPartyPlannerABI,
|
||||
functionName: 'getAllPools',
|
||||
args: [BigInt(offset), BigInt(limit)],
|
||||
});
|
||||
|
||||
setPools(result);
|
||||
|
||||
// Fetch details for each pool
|
||||
const details: PoolDetails[] = [];
|
||||
for (const poolAddress of result) {
|
||||
try {
|
||||
const [name, symbol, tokens] = await Promise.all([
|
||||
publicClient.readContract({
|
||||
address: poolAddress,
|
||||
abi: ERC20ABI,
|
||||
functionName: 'name',
|
||||
}).catch(() => 'Unknown Pool'),
|
||||
publicClient.readContract({
|
||||
address: poolAddress,
|
||||
abi: ERC20ABI,
|
||||
functionName: 'symbol',
|
||||
}).catch(() => 'POOL'),
|
||||
publicClient.readContract({
|
||||
address: poolAddress,
|
||||
abi: IPartyPoolABI,
|
||||
functionName: 'allTokens',
|
||||
}).catch(() => [] as readonly `0x${string}`[]),
|
||||
]);
|
||||
|
||||
details.push({
|
||||
address: poolAddress,
|
||||
name: name as string,
|
||||
symbol: symbol as string,
|
||||
tokens: tokens as readonly `0x${string}`[],
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Error fetching pool details for', poolAddress, err);
|
||||
// Add pool with fallback values
|
||||
details.push({
|
||||
address: poolAddress,
|
||||
name: 'Unknown Pool',
|
||||
symbol: 'POOL',
|
||||
tokens: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
setPoolDetails(details);
|
||||
} catch (err) {
|
||||
console.error('Error calling getAllPools:', err);
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch pools');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchPools();
|
||||
}, [publicClient, mounted, offset, limit]);
|
||||
|
||||
return {
|
||||
pools,
|
||||
poolDetails,
|
||||
loading,
|
||||
error,
|
||||
isReady: mounted,
|
||||
};
|
||||
}
|
||||
|
||||
export interface SwapMintAmounts {
|
||||
amountInUsed: bigint;
|
||||
fee: bigint;
|
||||
lpMinted: bigint;
|
||||
}
|
||||
|
||||
export function useSwapMintAmounts(
|
||||
poolAddress: `0x${string}` | undefined,
|
||||
inputTokenIndex: number | undefined,
|
||||
maxAmountIn: bigint | undefined
|
||||
) {
|
||||
const publicClient = usePublicClient();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [swapMintAmounts, setSwapMintAmounts] = useState<SwapMintAmounts | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// Handle hydration for Next.js static export
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!mounted || !poolAddress || inputTokenIndex === undefined || !maxAmountIn || maxAmountIn === BigInt(0)) {
|
||||
setLoading(false);
|
||||
setSwapMintAmounts(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchSwapMintAmounts = async () => {
|
||||
if (!publicClient) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
// Get chain ID and contract address
|
||||
const chainId = await publicClient.getChainId();
|
||||
const viewerAddress = (chainInfo as Record<string, { v1: { PartyPlanner: string; PartyPoolViewer: string } }>)[chainId.toString()]?.v1?.PartyPoolViewer;
|
||||
|
||||
if (!viewerAddress) {
|
||||
setError('IPartyPoolViewer contract not found for current chain');
|
||||
setSwapMintAmounts(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Call swapMintAmounts function
|
||||
const result = await publicClient.readContract({
|
||||
address: viewerAddress as `0x${string}`,
|
||||
abi: IPartyPoolViewerABI,
|
||||
functionName: 'swapMintAmounts',
|
||||
args: [poolAddress, BigInt(inputTokenIndex), maxAmountIn],
|
||||
}) as readonly [bigint, bigint, bigint];
|
||||
|
||||
setSwapMintAmounts({
|
||||
amountInUsed: result[0],
|
||||
fee: result[1],
|
||||
lpMinted: result[2],
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Error calling swapMintAmounts:', err);
|
||||
setError(err instanceof Error ? err.message : 'Failed to fetch swap mint amounts');
|
||||
setSwapMintAmounts(null);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchSwapMintAmounts();
|
||||
}, [publicClient, mounted, poolAddress, inputTokenIndex, maxAmountIn]);
|
||||
|
||||
return {
|
||||
swapMintAmounts,
|
||||
loading,
|
||||
error,
|
||||
isReady: mounted,
|
||||
};
|
||||
}
|
||||
@@ -357,4 +357,109 @@ export function useSwap() {
|
||||
gasEstimate,
|
||||
isEstimatingGas,
|
||||
};
|
||||
}
|
||||
|
||||
export function useSwapMint() {
|
||||
const publicClient = usePublicClient();
|
||||
const { data: walletClient } = useWalletClient();
|
||||
const [isSwapMinting, setIsSwapMinting] = useState(false);
|
||||
const [swapMintHash, setSwapMintHash] = useState<`0x${string}` | null>(null);
|
||||
const [swapMintError, setSwapMintError] = useState<string | null>(null);
|
||||
|
||||
const executeSwapMint = async (
|
||||
poolAddress: `0x${string}`,
|
||||
inputTokenAddress: `0x${string}`,
|
||||
inputTokenIndex: number,
|
||||
maxAmountIn: bigint
|
||||
) => {
|
||||
if (!walletClient || !publicClient) {
|
||||
setSwapMintError('Wallet not connected');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
setIsSwapMinting(true);
|
||||
setSwapMintError(null);
|
||||
setSwapMintHash(null);
|
||||
|
||||
const userAddress = walletClient.account.address;
|
||||
|
||||
// STEP 1: Approve the pool to spend the input token
|
||||
console.log('🔐 Approving token spend for swap mint...');
|
||||
console.log('Token to approve:', inputTokenAddress);
|
||||
console.log('Spender (pool):', poolAddress);
|
||||
console.log('Amount:', maxAmountIn.toString());
|
||||
|
||||
const approvalHash = await walletClient.writeContract({
|
||||
address: inputTokenAddress,
|
||||
abi: [
|
||||
{
|
||||
name: 'approve',
|
||||
type: 'function',
|
||||
stateMutability: 'nonpayable',
|
||||
inputs: [
|
||||
{ name: 'spender', type: 'address' },
|
||||
{ name: 'amount', type: 'uint256' }
|
||||
],
|
||||
outputs: [{ name: '', type: 'bool' }]
|
||||
}
|
||||
],
|
||||
functionName: 'approve',
|
||||
args: [poolAddress, maxAmountIn],
|
||||
});
|
||||
|
||||
console.log('✅ Approval transaction submitted:', approvalHash);
|
||||
await publicClient.waitForTransactionReceipt({ hash: approvalHash });
|
||||
console.log('✅ Approval confirmed');
|
||||
|
||||
// STEP 2: Calculate deadline (5 minutes from now)
|
||||
const deadline = BigInt(Math.floor(Date.now() / 1000) + 300); // 5 minutes = 300 seconds
|
||||
|
||||
console.log('🚀 Executing swapMint with params:', {
|
||||
pool: poolAddress,
|
||||
payer: userAddress,
|
||||
receiver: userAddress,
|
||||
inputTokenIndex,
|
||||
maxAmountIn: maxAmountIn.toString(),
|
||||
deadline: deadline.toString(),
|
||||
});
|
||||
|
||||
// STEP 3: Execute the swapMint transaction
|
||||
const hash = await walletClient.writeContract({
|
||||
address: poolAddress,
|
||||
abi: IPartyPoolABI,
|
||||
functionName: 'swapMint',
|
||||
args: [
|
||||
userAddress, // payer
|
||||
userAddress, // receiver
|
||||
BigInt(inputTokenIndex),
|
||||
maxAmountIn,
|
||||
deadline,
|
||||
],
|
||||
});
|
||||
|
||||
setSwapMintHash(hash);
|
||||
console.log('✅ SwapMint transaction submitted:', hash);
|
||||
|
||||
// Wait for transaction confirmation
|
||||
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
||||
console.log('✅ SwapMint transaction confirmed:', receipt);
|
||||
|
||||
return receipt;
|
||||
} catch (err) {
|
||||
const errorMessage = err instanceof Error ? err.message : 'SwapMint failed';
|
||||
setSwapMintError(errorMessage);
|
||||
console.error('❌ SwapMint error:', err);
|
||||
throw err;
|
||||
} finally {
|
||||
setIsSwapMinting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
executeSwapMint,
|
||||
isSwapMinting,
|
||||
swapMintHash,
|
||||
swapMintError,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user