Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/app/(walletConnected)/liquidity-pools/create-pool/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import { TCreatePoolPayload, MintInfo } from '@/features/liquidityPool/types'
import {
isBBAPool,
getBBAPositionInPool,
requiresBBAWrapping
} from '@/features/liquidityPool/utils'
import { createPoolValidation } from '@/features/liquidityPool/validation'
import { LoadingDialog } from '@/features/nfts/components/StatusDialog'
Expand Down Expand Up @@ -393,13 +392,20 @@ export default function CreatePool() {
setIsTokenDialogOpen(true)
}, [])

const resetTokenAmounts = useCallback(() => {
form.setValue('baseTokenAmount', '')
form.setValue('quoteTokenAmount', '')
}, [form])

// Auto-calculate quote amount based on price ratio
// Initial Price format: "X BaseToken per QuoteToken"
// Example: "1000 SHIB per USDT" means 1 USDT = 1000 SHIB, so 1 SHIB = 1/1000 USDT
const handleBaseAmountChange = useCallback(
(value: string) => {
form.setValue('baseTokenAmount', value, { shouldValidate: true })

if(value === '') return resetTokenAmounts()

// Auto-calculate quote amount if both tokens and initial price are set
const initialPrice = parseFloat(form.getValues('initialPrice'))
if (initialPrice && value && selectedBaseToken && selectedQuoteToken) {
Expand All @@ -409,13 +415,15 @@ export default function CreatePool() {
form.setValue('quoteTokenAmount', quoteAmount.toString(), { shouldValidate: true })
}
},
[form, selectedBaseToken, selectedQuoteToken]
[form, resetTokenAmounts, selectedBaseToken, selectedQuoteToken]
)

const handleQuoteAmountChange = useCallback(
(value: string) => {
form.setValue('quoteTokenAmount', value, { shouldValidate: true })

if (value === '') return resetTokenAmounts()

// Auto-calculate base amount if both tokens and initial price are set
const initialPrice = parseFloat(form.getValues('initialPrice'))
if (initialPrice && value && selectedBaseToken && selectedQuoteToken) {
Expand All @@ -425,7 +433,7 @@ export default function CreatePool() {
form.setValue('baseTokenAmount', baseAmount.toString(), { shouldValidate: true })
}
},
[form, selectedBaseToken, selectedQuoteToken]
[form, resetTokenAmounts, selectedBaseToken, selectedQuoteToken]
)

// Show loading state for tokens
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,20 @@ export default function LiquidityPoolDeposit({ params }: { params: { poolId: str
!hasInsufficientBalanceB &&
!depositMutation.isPending

const resetValue = () => {
setFromAmount('')
setToAmount('')
}

const handleFromAmountChange = (value: string) => {
setFromAmount(value)
if (value === '') return resetValue()
setLastChangedField('from')
}

const handleToAmountChange = (value: string) => {
setToAmount(value)
if (value === '') return resetValue()
setLastChangedField('to')
}

Expand Down
36 changes: 13 additions & 23 deletions src/app/(walletConnected)/liquidity-pools/detail/[poolId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ export default function PoolDetail({ params }: { params: { poolId: string } }) {
const router = useRouter()
const poolId = params.poolId

const [isInitialLoad, setIsInitialLoad] = useState<boolean>(true)
const [isOwnerTab, setIsOwnerTab] = useState<boolean>(false)
const isMobile = useIsMobile()

Expand Down Expand Up @@ -182,16 +181,7 @@ export default function PoolDetail({ params }: { params: { poolId: string } }) {
}
}, [getTransactionsByPoolId.error, getTransactionsByPoolId.isError])

useEffect(() => {
if (!(getPoolById.isLoading || getTransactionsByPoolId.isLoading)) {
setIsInitialLoad(false)
}
}, [getPoolById.isLoading, getTransactionsByPoolId.isLoading])

if (
isInitialLoad &&
(getPoolById.isLoading || getTransactionsByPoolId.isLoading || getUserStats.isLoading)
)
if (getPoolById.isLoading || getTransactionsByPoolId.isLoading || getUserStats.isLoading)
return (
<div className="w-full mx-auto 2xl:max-w-7xl lg:max-w-5xl md:max-w-2xl px-[15px]">
<Button
Expand All @@ -216,7 +206,7 @@ export default function PoolDetail({ params }: { params: { poolId: string } }) {
<HiOutlineArrowNarrowLeft />
<h4>Pools</h4>
</Button>
{getPoolById.isLoading ? (
{getPoolById.isRefetching ? (
<div className="flex flex-wrap items-center justify-between gap-4">
<div className="flex items-center gap-2">
<Skeleton className="h-7 w-7 rounded-full" />
Expand Down Expand Up @@ -340,33 +330,33 @@ export default function PoolDetail({ params }: { params: { poolId: string } }) {
mintBAmount={mintBAmount}
mintASymbol={pool?.mintA?.symbol ?? ''}
mintBSymbol={pool?.mintB?.symbol ?? ''}
isLoading={getPoolById.isLoading}
isLoading={getPoolById.isRefetching}
/>
</div>
<div className="md:mt-6 mt-3 grid grid-cols-2 lg:flex lg:gap-y-0 gap-y-3 items-center justify-between">
<StatsItem
isLoading={getPoolById.isLoading}
isLoading={getPoolById.isRefetching}
title="APR(7 days)"
info="Weekly Percentage Rate earned by liquidity providers from trading fees and rewards."
content={`${pool?.apr24h.toFixed(2) ?? 0.0}%`}
/>
<hr className="w-px h-12 lg:block hidden bg-light-grey border-0" />
<StatsItem
isLoading={getPoolById.isLoading}
isLoading={getPoolById.isRefetching}
title="TVL"
info="The total dollar value of assets locked in this liquidity pool."
content={`$${pool?.tvl.toLocaleString() ?? 0}`}
/>
<hr className="w-px h-12 lg:block hidden bg-light-grey border-0" />
<StatsItem
isLoading={getPoolById.isLoading}
isLoading={getPoolById.isRefetching}
title="Fees(24h)"
info="Trading fees generated by this pool in the past 24 hours."
content={`$${pool?.fees24h.toFixed(3) ?? 0}`}
/>
<hr className="w-px h-12 lg:block hidden bg-light-grey border-0" />
<StatsItem
isLoading={getPoolById.isLoading}
isLoading={getPoolById.isRefetching}
title="Volume(24h)"
info="Total swap volume (trades) processed in this pool within the last 24 hours."
content={`$${pool?.volume24h.toFixed(3) ?? 0}`}
Expand Down Expand Up @@ -462,33 +452,33 @@ export default function PoolDetail({ params }: { params: { poolId: string } }) {
mintBAmount={userStats?.userReserveB ?? 0}
mintASymbol={pool?.mintA?.symbol ?? ''}
mintBSymbol={pool?.mintB?.symbol ?? ''}
isLoading={getUserStats.isLoading}
isLoading={getUserStats.isRefetching}
/>
</div>
<div className="md:mt-6 mt-3 grid grid-cols-2 lg:flex lg:gap-y-0 gap-y-3 items-center justify-between">
<StatsItem
isLoading={getUserStats.isLoading}
isLoading={getUserStats.isRefetching}
title="My Pool Share (%)"
info="This is the percentage of the total liquidity pool that you currently own."
content={`${((userStats?.userShare ?? 0) * 100).toFixed(2)}%`}
/>
<hr className="w-px h-12 lg:block hidden bg-light-grey border-0" />
<StatsItem
isLoading={getUserStats.isLoading}
isLoading={getUserStats.isRefetching}
title="My Liquidity Value"
info="The estimated dollar value of the tokens you've contributed to this pool."
content={`$${userStats?.userReserveTotalPrice.toLocaleString() ?? 0}`}
/>
<hr className="w-px h-12 lg:block hidden bg-light-grey border-0" />
<StatsItem
isLoading={getUserStats.isLoading}
isLoading={getUserStats.isRefetching}
title="LP Tokens Held"
info="The total number of LP (liquidity provider) tokens you own — including both staked and unstaked."
content={`${userStats?.userLPToken.toLocaleString() ?? 0} LP`}
/>
<hr className="w-px h-12 lg:block hidden bg-light-grey border-0" />
<StatsItem
isLoading={getUserStats.isLoading}
isLoading={getUserStats.isRefetching}
title="Fee Earnings(24h)"
info="Total amount you've earned from trading fees within the last 24 hours."
content={`$${userStats?.dailyFeeEarnings.toFixed(3) ?? 0}`}
Expand All @@ -499,7 +489,7 @@ export default function PoolDetail({ params }: { params: { poolId: string } }) {
</div>
<div className="flex flex-col md:space-y-6 space-y-3 md:mt-14 mt-5">
<h2 className="font-semibold lg:text-2xl text-xl text-main-black">Transactions</h2>
{getTransactionsByPoolId.isLoading ? (
{getTransactionsByPoolId.isRefetching ? (
<PoolDetailTransactionSkeleton />
) : (
<TransactionDataTable
Expand Down
31 changes: 26 additions & 5 deletions src/features/liquidityPool/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const useGetPools = () => {
const getAllTokenPrices = useGetAllTokenPrices()
const allTokenPrices = getAllTokenPrices.data
const getPoolsWithPrices = useQuery<TGetPoolsResponse>({
queryKey: [SERVICES_KEY.POOL.GET_POOLS, allTokenPrices],
queryKey: [SERVICES_KEY.POOL.GET_POOLS],
queryFn: async () => {
const poolAccounts = await getPoolAccounts(connection)
const batchSize = 10
Expand Down Expand Up @@ -122,7 +122,7 @@ export const useGetPoolById = ({ poolId }: { poolId: string }) => {
const allTokenPrices = getAllTokenPrices.data

const getPoolWithPricesQuery = useQuery<TGetPoolByIdResponse>({
queryKey: [SERVICES_KEY.POOL.GET_POOL_BY_ID, poolId, allTokenPrices],
queryKey: [SERVICES_KEY.POOL.GET_POOL_BY_ID, poolId],
queryFn: async () => {
const pubKey = new PublicKey(poolId)
const accountInfo = await connection.getAccountInfo(pubKey)
Expand Down Expand Up @@ -805,6 +805,14 @@ export const useCreatePool = () => {
baseAmountDaltons
)

// transaction approval
const approveIx = createApproveInstruction(
userBaseTokenAccount,
ownerAddress,
ownerAddress,
baseAmountDaltons
)

// Transfer BBA to pool (using special BBA handling)
console.log('🔄 Transferring BBA to pool account...')
const transferBBAIx = SystemProgram.transfer({
Expand All @@ -817,7 +825,12 @@ export const useCreatePool = () => {
const syncBBAIx = createSyncNativeInstruction(swapTokenBAccount)

// Combine all transfers
const liquidityTx = new Transaction().add(transferBaseIx, transferBBAIx, syncBBAIx)
const liquidityTx = new Transaction().add(
approveIx,
transferBaseIx,
transferBBAIx,
syncBBAIx
)
const liquiditySig = await sendTransactionWithRetry(
liquidityTx,
connection,
Expand Down Expand Up @@ -891,8 +904,16 @@ export const useCreatePool = () => {
quoteAmountDaltons
)

// approval instruction
const approveIx = createApproveInstruction(
userQuoteTokenAccount,
ownerAddress,
ownerAddress,
baseAmountDaltons
)

// Send initial liquidity transfer
const liquidityTx = new Transaction().add(transferBaseIx, transferQuoteIx)
const liquidityTx = new Transaction().add(approveIx, transferBaseIx, transferQuoteIx)
const liquiditySig = await sendTransactionWithRetry(
liquidityTx,
connection,
Expand Down Expand Up @@ -1454,7 +1475,7 @@ export const useDepositToPool = () => {
try {
const signature = await sendTransaction(transaction, connection, {
skipPreflight: false,
preflightCommitment: 'confirmed',
preflightCommitment: 'confirmed'
})
console.log('✅ Transaction sent successfully:', signature)

Expand Down