diff --git a/src/abacus-ts/calculators/subaccount.ts b/src/abacus-ts/calculators/subaccount.ts index 0e03ec653..f8928dc2d 100644 --- a/src/abacus-ts/calculators/subaccount.ts +++ b/src/abacus-ts/calculators/subaccount.ts @@ -291,7 +291,7 @@ function calculatePositionDerivedExtra( }; } -export function createUsdcDepositOperation({ +export function createUsdcDepositOperations({ subaccountNumber, depositAmount, }: { @@ -310,7 +310,7 @@ export function createUsdcDepositOperation({ }; } -export function createUsdcWithdrawalOperation({ +export function createUsdcWithdrawalOperations({ subaccountNumber, withdrawAmount, }: { @@ -344,11 +344,22 @@ function modifyUsdcAssetPosition( let childSubaccount: ChildSubaccountData | undefined = parentSubaccountData.childSubaccounts[subaccountNumber]; - if (childSubaccount) { + if (childSubaccount != null) { // Modify childSubaccount - if (childSubaccount.assetPositions.USDC) { - const currentUsdcSizeBN = MustBigNumber(childSubaccount.assetPositions.USDC.size); - childSubaccount.assetPositions.USDC.size = currentUsdcSizeBN.plus(sizeBN).toString(); + if (childSubaccount.assetPositions.USDC != null) { + const size = MustBigNumber(childSubaccount.assetPositions.USDC.size).plus(sizeBN).toString(); + const assetPositions = { + ...childSubaccount.assetPositions, + USDC: { + ...childSubaccount.assetPositions.USDC, + size, + }, + }; + + childSubaccount = { + ...childSubaccount, + assetPositions, + }; } else { if (sizeBN.gt(0)) { childSubaccount.assetPositions.USDC = { @@ -378,7 +389,10 @@ function modifyUsdcAssetPosition( }; } - parentSubaccountData.childSubaccounts[subaccountNumber] = childSubaccount; + parentSubaccountData.childSubaccounts = { + ...parentSubaccountData.childSubaccounts, + [subaccountNumber]: childSubaccount, + }; } export function applyOperationsToSubaccount( diff --git a/src/abacus-ts/ontology.ts b/src/abacus-ts/ontology.ts index c027ce258..5986e194e 100644 --- a/src/abacus-ts/ontology.ts +++ b/src/abacus-ts/ontology.ts @@ -3,8 +3,6 @@ import { getCurrentMarketId } from '@/state/perpetualsSelectors'; import { useCurrentMarketHistoricalFunding } from './rest/funding'; import { - createSelectParentSubaccountPositionsPostOp, - createSelectParentSubaccountSummaryPostOp, getCurrentMarketAccountFills, selectAccountFills, selectAccountFillsLoading, @@ -18,6 +16,12 @@ import { selectParentSubaccountSummary, selectParentSubaccountSummaryLoading, } from './selectors/account'; +import { + createSelectParentSubaccountPositionsDeposit, + createSelectParentSubaccountPositionsWithdrawal, + createSelectParentSubaccountSummaryDeposit, + createSelectParentSubaccountSummaryWithdrawal, +} from './selectors/accountActions'; import { selectAllAssetsInfo, selectAllAssetsInfoLoading, @@ -99,9 +103,15 @@ export const BonsaiHelpers = { fills: getCurrentMarketAccountFills, }, }, - modify: { - parentSubaccountSummary: createSelectParentSubaccountSummaryPostOp, - parentSubaccountPositions: createSelectParentSubaccountPositionsPostOp, + account: { + deposit: { + parentSubaccountSummary: createSelectParentSubaccountSummaryDeposit, + parentSubaccountPositions: createSelectParentSubaccountPositionsDeposit, + }, + withdraw: { + parentSubaccountSummary: createSelectParentSubaccountSummaryWithdrawal, + parentSubaccountPositions: createSelectParentSubaccountPositionsWithdrawal, + }, }, } as const satisfies NestedSelectors; diff --git a/src/abacus-ts/selectors/account.ts b/src/abacus-ts/selectors/account.ts index 7b89ef558..a3d42465a 100644 --- a/src/abacus-ts/selectors/account.ts +++ b/src/abacus-ts/selectors/account.ts @@ -14,14 +14,12 @@ import { calculateOrderHistory, } from '../calculators/orders'; import { - applyOperationsToSubaccount, calculateMarketsNeededForSubaccount, calculateParentSubaccountPositions, calculateParentSubaccountSummary, } from '../calculators/subaccount'; import { calculateTransfers } from '../calculators/transfers'; import { mergeLoadableStatus } from '../lib/mapLoadable'; -import { SubaccountBatchedOperations } from '../types/operationTypes'; import { selectRawFillsLiveData, selectRawFillsRest, @@ -54,7 +52,7 @@ const selectRelevantMarketsList = createAppSelector( } ); -const selectRelevantMarketsData = createAppSelector( +export const selectRelevantMarketsData = createAppSelector( [selectRelevantMarketsList, selectRawMarketsData], (marketIds, markets) => { if (markets == null || marketIds == null) { @@ -79,24 +77,6 @@ export const selectParentSubaccountSummary = createAppSelector( } ); -export const createSelectParentSubaccountSummaryPostOp = () => - createAppSelector( - [ - selectRawParentSubaccountData, - selectRelevantMarketsData, - (_s, operations: SubaccountBatchedOperations) => operations, - ], - (parentSubaccount, markets, operations) => { - if (parentSubaccount == null || markets == null) { - return undefined; - } - - const modifiedParentSubaccount = applyOperationsToSubaccount(parentSubaccount, operations); - const result = calculateParentSubaccountSummary(modifiedParentSubaccount, markets); - return result; - } - ); - export const selectParentSubaccountPositions = createAppSelector( [selectRawParentSubaccountData, selectRelevantMarketsData], (parentSubaccount, markets) => { @@ -107,23 +87,6 @@ export const selectParentSubaccountPositions = createAppSelector( } ); -export const createSelectParentSubaccountPositionsPostOp = () => - createAppSelector( - [ - selectRawParentSubaccountData, - selectRelevantMarketsData, - (_s, operations: SubaccountBatchedOperations) => operations, - ], - (parentSubaccount, markets, operations) => { - if (parentSubaccount == null || markets == null) { - return undefined; - } - - const modifiedParentSubaccount = applyOperationsToSubaccount(parentSubaccount, operations); - return calculateParentSubaccountPositions(modifiedParentSubaccount, markets); - } - ); - export const selectParentSubaccountSummaryLoading = createAppSelector( [selectRawParentSubaccount, selectRawMarkets], mergeLoadableStatus diff --git a/src/abacus-ts/selectors/accountActions.ts b/src/abacus-ts/selectors/accountActions.ts new file mode 100644 index 000000000..3c6b267fa --- /dev/null +++ b/src/abacus-ts/selectors/accountActions.ts @@ -0,0 +1,129 @@ +import { shallowEqual } from 'react-redux'; + +import { createAppSelector } from '@/state/appTypes'; + +import { + applyOperationsToSubaccount, + calculateParentSubaccountPositions, + calculateParentSubaccountSummary, + createUsdcDepositOperations, + createUsdcWithdrawalOperations, +} from '../calculators/subaccount'; +import { selectRelevantMarketsData } from './account'; +import { selectRawParentSubaccountData } from './base'; + +export const createSelectParentSubaccountSummaryDeposit = () => + createAppSelector( + [ + selectRawParentSubaccountData, + selectRelevantMarketsData, + ( + _s, + input: { + subaccountNumber: number; + depositAmount: string; + } + ) => input, + ], + (parentSubaccount, markets, depositInputs) => { + if (parentSubaccount == null || markets == null) { + return undefined; + } + + const operations = createUsdcDepositOperations(depositInputs); + const modifiedParentSubaccount = applyOperationsToSubaccount(parentSubaccount, operations); + const result = calculateParentSubaccountSummary(modifiedParentSubaccount, markets); + return result; + }, + { + // use shallow equal for result so that we only update when these specific keys differ + memoizeOptions: { resultEqualityCheck: shallowEqual }, + } + ); + +export const createSelectParentSubaccountPositionsDeposit = () => + createAppSelector( + [ + selectRawParentSubaccountData, + selectRelevantMarketsData, + ( + _s, + input: { + subaccountNumber: number; + depositAmount: string; + } + ) => input, + ], + (parentSubaccount, markets, depositInputs) => { + if (parentSubaccount == null || markets == null) { + return undefined; + } + + const operations = createUsdcDepositOperations(depositInputs); + const modifiedParentSubaccount = applyOperationsToSubaccount(parentSubaccount, operations); + const result = calculateParentSubaccountPositions(modifiedParentSubaccount, markets); + return result; + }, + { + // use shallow equal for result so that we only update when these specific keys differ + memoizeOptions: { resultEqualityCheck: shallowEqual }, + } + ); + +export const createSelectParentSubaccountSummaryWithdrawal = () => + createAppSelector( + [ + selectRawParentSubaccountData, + selectRelevantMarketsData, + ( + _s, + input: { + subaccountNumber: number; + withdrawAmount: string; + } + ) => input, + ], + (parentSubaccount, markets, withdrawalInputs) => { + if (parentSubaccount == null || markets == null) { + return undefined; + } + + const operations = createUsdcWithdrawalOperations(withdrawalInputs); + const modifiedParentSubaccount = applyOperationsToSubaccount(parentSubaccount, operations); + const result = calculateParentSubaccountSummary(modifiedParentSubaccount, markets); + return result; + }, + { + // use shallow equal for result so that we only update when these specific keys differ + memoizeOptions: { resultEqualityCheck: shallowEqual }, + } + ); + +export const createSelectParentSubaccountPositionsWithdrawal = () => + createAppSelector( + [ + selectRawParentSubaccountData, + selectRelevantMarketsData, + ( + _s, + input: { + subaccountNumber: number; + withdrawAmount: string; + } + ) => input, + ], + (parentSubaccount, markets, withdrawalInputs) => { + if (parentSubaccount == null || markets == null) { + return undefined; + } + + const operations = createUsdcWithdrawalOperations(withdrawalInputs); + const modifiedParentSubaccount = applyOperationsToSubaccount(parentSubaccount, operations); + const result = calculateParentSubaccountPositions(modifiedParentSubaccount, markets); + return result; + }, + { + // use shallow equal for result so that we only update when these specific keys differ + memoizeOptions: { resultEqualityCheck: shallowEqual }, + } + ); diff --git a/src/views/dialogs/DepositDialog2/queries.ts b/src/views/dialogs/DepositDialog2/queries.ts index 6d906a985..1dee08050 100644 --- a/src/views/dialogs/DepositDialog2/queries.ts +++ b/src/views/dialogs/DepositDialog2/queries.ts @@ -1,5 +1,6 @@ import { useMemo } from 'react'; +import { BonsaiHelpers } from '@/abacus-ts/ontology'; import { BalanceRequest, RouteRequest, SkipClient } from '@skip-go/client'; import { useQuery } from '@tanstack/react-query'; import { Chain, parseUnits } from 'viem'; @@ -14,6 +15,7 @@ import { WalletNetworkType } from '@/constants/wallets'; import { useSkipClient } from '@/hooks/transfers/skipClient'; import { useAccounts } from '@/hooks/useAccounts'; +import { useParameterizedSelector } from '@/hooks/useParameterizedSelector'; import { SourceAccount } from '@/state/wallet'; @@ -147,3 +149,15 @@ export function useDepositRoutes(token: TokenForTransfer, amount: string) { placeholderData: (prev) => prev, }); } + +export function useDepositDeltas({ depositAmount }: { depositAmount: string }) { + const modifiedParentSubaccount = useParameterizedSelector( + BonsaiHelpers.account.deposit.parentSubaccountSummary, + { + subaccountNumber: 0, + depositAmount, + } + ); + + return modifiedParentSubaccount; +} diff --git a/src/views/dialogs/WithdrawDialog2/queries.ts b/src/views/dialogs/WithdrawDialog2/queries.ts index 6e7fce80e..d76e702fb 100644 --- a/src/views/dialogs/WithdrawDialog2/queries.ts +++ b/src/views/dialogs/WithdrawDialog2/queries.ts @@ -1,3 +1,4 @@ +import { BonsaiHelpers } from '@/abacus-ts/ontology'; import { RouteRequest, SkipClient } from '@skip-go/client'; import { useQuery } from '@tanstack/react-query'; import { parseUnits } from 'viem'; @@ -7,6 +8,7 @@ import { timeUnits } from '@/constants/time'; import { DYDX_CHAIN_USDC_DENOM, TokenForTransfer } from '@/constants/tokens'; import { useSkipClient } from '@/hooks/transfers/skipClient'; +import { useParameterizedSelector } from '@/hooks/useParameterizedSelector'; async function getSkipWithdrawalRoutes( skipClient: SkipClient, @@ -53,3 +55,15 @@ export function useWithdrawalRoutes({ retry: false, }); } + +export function useWithdrawalDeltas({ withdrawAmount }: { withdrawAmount: string }) { + const modifiedParentSubaccount = useParameterizedSelector( + BonsaiHelpers.account.withdraw.parentSubaccountSummary, + { + subaccountNumber: 0, + withdrawAmount, + } + ); + + return modifiedParentSubaccount; +}