Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
46c0ea4
Add max balance for trading based on trasanction cost
vkulinich-cl May 19, 2026
4908cae
add max balance to dca
vkulinich-cl May 19, 2026
7949717
fix negative max balance
vkulinich-cl May 27, 2026
00b6c1a
fix lint
vkulinich-cl May 27, 2026
dc2ea38
fix balance updating
vkulinich-cl May 28, 2026
c9bb4c7
Merge branch 'master' into feat/trade-max-balance
vkulinich-cl Jun 8, 2026
6d2cd47
Merge branch 'master' into feat/trade-max-balance
vkulinich-cl Jun 15, 2026
20969ec
add max balance across the app
vkulinich-cl Jun 18, 2026
bd1c22d
fix lint
vkulinich-cl Jun 18, 2026
d4e4660
Merge branch 'master' into feat/trade-max-balance
vkulinich-cl Jun 24, 2026
eb321a1
add missing form's max balances
vkulinich-cl Jun 25, 2026
736fdb6
support weth signing
vkulinich-cl Jun 26, 2026
4616d68
Merge branch 'master' into feat/trade-max-balance
vkulinich-cl Jun 29, 2026
56a3a96
add max balance with fee to MM
vkulinich-cl Jun 30, 2026
cf99318
Merge branch 'master' into feat/trade-max-balance
vkulinich-cl Jun 30, 2026
c413acd
support GHO as repay asset
vkulinich-cl Jun 30, 2026
f43bc2e
fix rounding
vkulinich-cl Jun 30, 2026
7a34473
Merge branch 'master' into feat/trade-max-balance
vkulinich-cl Jul 1, 2026
ed23d7a
update estimation fee tx
vkulinich-cl Jul 2, 2026
2afb311
fix repay estimation tx
vkulinich-cl Jul 2, 2026
7c32b67
add max baalnce for supply isolated asset
vkulinich-cl Jul 3, 2026
32912e7
fix inner evm call fee estimation
vkulinich-cl Jul 3, 2026
7b062d2
Merge branch 'master' into feat/trade-max-balance
vkulinich-cl Jul 22, 2026
98620f8
Address PR comments
vkulinich-cl Jul 22, 2026
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
10 changes: 10 additions & 0 deletions apps/main/src/modules/borrow/BorrowContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import { ApyProvider } from "@/modules/borrow/context/ApyContext"
import { useExternalApyData } from "@/modules/borrow/hooks/useExternalApyData"
import { useFormatReserve } from "@/modules/borrow/hooks/useFormatReserve"
import { useCreateBatchTx } from "@/modules/transactions/hooks/useBatchTx"
import { useMaxBalance } from "@/modules/transactions/hooks/useMaxBalance"
import { transformEvmCallToPapiTx } from "@/modules/transactions/utils/tx"
import { useAssets } from "@/providers/assetsProvider"
import { useRpcProvider } from "@/providers/rpcProvider"
import { useTransactionsStore } from "@/states/transactions"

Expand All @@ -37,6 +39,7 @@ export const BorrowContextProvider: React.FC<PropsWithChildren> = ({
const createBatchTx = useCreateBatchTx()
const { evm, dataEnv, papi } = useRpcProvider()
const squidClient = useSquidClient()
const { getRelatedAToken } = useAssets()
const { market } = useSearch({ from: "/borrow" })

const selectedMarket = market || defaultMarketByEnv[dataEnv]
Expand All @@ -61,18 +64,25 @@ export const BorrowContextProvider: React.FC<PropsWithChildren> = ({
[createTransaction, createBatchTx, papi],
)

const getRelatedATokenId = useCallback(
(id: string) => getRelatedAToken(id)?.id,
[getRelatedAToken],
)

return (
<ApyProvider>
<MoneyMarketProvider
market={selectedMarket}
provider={evm.transport}
squidClient={squidClient}
onCreateTransaction={createTx}
useMaxBalance={useMaxBalance}
formatCurrency={createFormatterFn(t, "currency")}
formatNumber={createFormatterFn(t, "number")}
formatPercent={createFormatterFn(t, "percent")}
formatReserve={useFormatReserve()}
externalApyData={useExternalApyData()}
getRelatedATokenId={getRelatedATokenId}
>
{children}
</MoneyMarketProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,11 @@ export const AddIsolatedLiquidityForm = ({

const {
form,
getMaxBalance,
reserveA,
reserveB,
ratio,
mutation,
assetABalance,
assetBBalance,
assetAMeta,
assetBMeta,
shares,
Expand Down Expand Up @@ -127,7 +126,7 @@ export const AddIsolatedLiquidityForm = ({
assetFieldName="assetA"
amountFieldName="amountA"
assets={[]}
maxBalance={assetABalance}
maxBalance={getMaxBalance(assetAMeta)}
disabledAssetSelector
onAmountChange={(value) => {
form.setValue("lastUpdated", "assetA")
Expand Down Expand Up @@ -166,7 +165,7 @@ export const AddIsolatedLiquidityForm = ({
assetFieldName="assetB"
amountFieldName="amountB"
assets={[]}
maxBalance={assetBBalance}
maxBalance={getMaxBalance(assetBMeta)}
disabledAssetSelector
onAmountChange={(value) => {
form.setValue("lastUpdated", "assetB")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ import { PoolToken } from "@/api/pools"
import { spotPriceQuery } from "@/api/spotPrice"
import { TXYKConsts, XYKPoolWithLiquidity } from "@/api/xyk"
import { useXYKFarmMinShares } from "@/modules/liquidity/components/JoinFarms/JoinFarms.utils"
import {
useFormMaxBalanceWithFee,
ValidateFormMaxBalanceWithFee,
} from "@/modules/transactions/hooks/useFormMaxBalanceWithFee"
import { TShareToken } from "@/providers/assetsProvider"
import { useRpcProvider } from "@/providers/rpcProvider"
import { useAccountBalances } from "@/states/account"
import { useTransactionsStore } from "@/states/transactions"
import { scale, scaleHuman } from "@/utils/formatting"
import { positive, required, validateFieldMaxBalance } from "@/utils/validators"
import { positive, required } from "@/utils/validators"

export const orders = ["assetA", "assetB"] as const
type Order = (typeof orders)[number]
Expand All @@ -35,17 +38,16 @@ export type TAddIsolatedLiquidityFormValues = {
}

export const useAddIsolatedLiquidityZod = (
balanceA: string,
balanceB: string,
validateBalance: ValidateFormMaxBalanceWithFee,
minTradingLimit: bigint,
minPoolLiquidity: bigint,
) => {
const { t } = useTranslation("liquidity")

return z
.object({
amountA: required.pipe(positive).check(validateFieldMaxBalance(balanceA)),
amountB: required.check(validateFieldMaxBalance(balanceB)),
amountA: required.pipe(positive),
amountB: required,
assetA: z.custom<TAssetData>(),
assetB: z.custom<TAssetData>(),
lastUpdated: z.literal(["assetA", "assetB"]),
Expand All @@ -55,6 +57,10 @@ export const useAddIsolatedLiquidityZod = (
error: t("liquidity.add.modal.validation.minPoolLiquidity"),
}),
})
.check(
validateBalance("amountA", (form) => [form.assetA, form.amountA]),
validateBalance("amountB", (form) => [form.assetB, form.amountB]),
)
.refine(
({ amountA, assetA }) => {
const minAssetATradingLimit = Big(
Expand Down Expand Up @@ -104,7 +110,6 @@ export const useAddIsolatedLiquidity = ({
const { t } = useTranslation("liquidity")
const { papi } = useRpcProvider()
const createTransaction = useTransactionsStore((s) => s.createTransaction)
const { getTransferableBalance } = useAccountBalances()
const { data: farms } = useIsolatedPoolFarms(shareTokenMeta.poolAddress)
const activeFarms = farms?.filter((farm) => farm.apr !== "0") ?? []
const isFarms = activeFarms.length > 0
Expand All @@ -117,22 +122,22 @@ export const useAddIsolatedLiquidity = ({

const [assetAMeta, assetBMeta] = shareTokenMeta.assets

const assetABalance = scaleHuman(
getTransferableBalance(assetAMeta.id),
assetAMeta.decimals,
)
const assetBBalance = scaleHuman(
getTransferableBalance(assetBMeta.id),
assetBMeta.decimals,
)

const { data: spotPriceData, isPending: isSpotPricePending } = useQuery(
spotPriceQuery(rpc, assetAMeta.id, assetBMeta.id),
)

const addLiquidityTx = papi.tx.XYK.add_liquidity({
asset_a: Number(assetAMeta.id),
asset_b: Number(assetBMeta.id),
amount_a: BigInt(scale("1", assetAMeta.decimals)),
amount_b_max_limit: BigInt(scale("1", assetBMeta.decimals)),
})

const { validateBalance, getMaxBalance } =
useFormMaxBalanceWithFee(addLiquidityTx)

const zodSchema = useAddIsolatedLiquidityZod(
assetABalance,
assetBBalance,
validateBalance,
pool.minTradingLimit,
consts.minPoolLiquidity,
)
Expand Down Expand Up @@ -236,12 +241,11 @@ export const useAddIsolatedLiquidity = ({

return {
form,
getMaxBalance,
reserveA,
reserveB,
ratio,
mutation,
assetABalance,
assetBBalance,
assetAMeta,
assetBMeta,
shares,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ import {
useOmnipoolAssetsData,
useOmnipoolMinLiquidity,
} from "@/api/omnipool"
import i18n from "@/i18n"
import { useMinOmnipoolFarmJoin } from "@/modules/liquidity/components/JoinFarms/JoinFarms.utils"
import { useFormMaxBalanceWithFee } from "@/modules/transactions/hooks/useFormMaxBalanceWithFee"
import { AnyTransaction } from "@/modules/transactions/types"
import { useAssets } from "@/providers/assetsProvider"
import { useRpcProvider } from "@/providers/rpcProvider"
import { useAccountBalances } from "@/states/account"
import { useTradeSettings } from "@/states/tradeSettings"
import { useTransactionsStore } from "@/states/transactions"
import { scale, scaleHuman, toDecimal } from "@/utils/formatting"
import { positive, required, validateMaxBalance } from "@/utils/validators"
import { scale, scaleHuman } from "@/utils/formatting"
import { positive, required } from "@/utils/validators"

export type TAddLiquidityFormValues = { amount: string; asset: TAssetData }

Expand Down Expand Up @@ -200,38 +200,30 @@ export const useAddLiquidityForm = ({
initialAmount,
selectedAsset,
rule,
tx,
}: {
selectedAsset: TAssetData
initialAmount?: string
rule?: ZodType<string, string> | undefined
tx: AnyTransaction | null
}) => {
const { getTransferableBalance } = useAccountBalances()
const { validateBalance, getMaxBalance } = useFormMaxBalanceWithFee(tx, 3)

const form = useForm<TAddLiquidityFormValues>({
mode: "onChange",
defaultValues: { amount: initialAmount ?? "", asset: selectedAsset },
resolver: rule
? standardSchemaResolver(
z.object({ amount: rule, asset: z.custom<TAssetData>() }).refine(
(values) => {
return validateMaxBalance(
toDecimal(
getTransferableBalance(values.asset.id),
values.asset.decimals,
),
values.amount,
)
},
{
message: i18n.t("error.maxBalance"),
path: ["amount"],
},
),
z
.object({ amount: rule, asset: z.custom<TAssetData>() })
.check(
validateBalance("amount", (form) => [form.asset, form.amount]),
),
)
: undefined,
})

return form
return { form, getMaxBalance }
}

export const useAddLiquidity = ({
Expand Down Expand Up @@ -264,19 +256,26 @@ export const useAddLiquidity = ({
: false

const addLiquidityZod = useAddToOmnipoolZod(poolId)
const underlyingAssetId = isErc20Asset
? getErc20AToken(poolId)?.underlyingAssetId
: undefined

const form = useAddLiquidityForm({
const addLiquidityTx = papi.tx.Omnipool.add_liquidity_with_limit({
asset: Number(poolId),
amount: BigInt(scale("1", poolMeta.decimals)),
min_shares_limit: 0n,
})

const { form, getMaxBalance } = useAddLiquidityForm({
initialAmount: "",
selectedAsset: poolMeta,
rule: addLiquidityZod,
tx: addLiquidityTx,
})

const amount = Big(form.watch("amount") || "0")
const selectedAsset = form.watch("asset")
const isErc20SelectedAsset = isErc20AToken(selectedAsset)
const underlyingAssetId = isErc20Asset
? getErc20AToken(poolId)?.underlyingAssetId
: undefined

const { isJoinFarms, joinFarmErrorMessage, activeFarms } =
useCheckJoinOmnipoolFarm({
Expand Down Expand Up @@ -380,6 +379,7 @@ export const useAddLiquidity = ({

return {
form,
getMaxBalance,
liquidityShares,
isFarms,
activeFarms,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const AddLiquidity: FC<AddLiquidityProps> = ({

const {
form,
getMaxBalance,
liquidityShares,
poolMeta,
activeFarms,
Expand All @@ -58,7 +59,7 @@ export const AddLiquidity: FC<AddLiquidityProps> = ({
healthFactor,
} = useAddLiquidity({ poolId: id, onSubmitted })

const { formState, handleSubmit } = form
const { formState, handleSubmit, watch } = form
const customErrors = getCustomErrors(formState.errors.amount)

return (
Expand All @@ -75,6 +76,7 @@ export const AddLiquidity: FC<AddLiquidityProps> = ({
assetFieldName="asset"
amountFieldName="amount"
assets={underlyingAssetMeta ? [underlyingAssetMeta, poolMeta] : []}
maxBalance={getMaxBalance(watch("asset"))}
sx={{ pt: 0 }}
disabledAssetSelector={!underlyingAssetMeta}
/>
Expand Down
Loading
Loading