From 950448b8eb978073813f02ff95dc13a5fae2b22e Mon Sep 17 00:00:00 2001 From: fr1j0 Date: Fri, 8 May 2026 14:11:41 -0400 Subject: [PATCH] Reduce conservative RPC waste --- .../tractor/soil-event-query.test.ts | 41 +++++++++++++++++++ src/components/nav/nav/Navbar.tsx | 24 +++-------- src/constants/query.ts | 8 ++-- src/lib/Tractor/sowOrder/index.ts | 1 + src/lib/Tractor/sowOrder/soil-event-query.ts | 34 +++++++++++++++ src/lib/Tractor/sowOrder/tractor-sow.ts | 9 ++-- src/state/queryKeys.ts | 2 + src/state/tractor/useTractorSowOrders.ts | 9 +++- src/state/use3PSiloWrappedTokenData.ts | 2 + src/state/useFarmerSilo.ts | 2 + 10 files changed, 104 insertions(+), 28 deletions(-) create mode 100644 src/__tests__/tractor/soil-event-query.test.ts create mode 100644 src/lib/Tractor/sowOrder/soil-event-query.ts diff --git a/src/__tests__/tractor/soil-event-query.test.ts b/src/__tests__/tractor/soil-event-query.test.ts new file mode 100644 index 000000000..d21574e3a --- /dev/null +++ b/src/__tests__/tractor/soil-event-query.test.ts @@ -0,0 +1,41 @@ +import { TIME_TO_BLOCKS } from "@/constants/blocks"; +import { getSoilEventQueryOptions } from "@/lib/Tractor/sowOrder/soil-event-query"; +import { describe, expect, it } from "vitest"; + +describe("getSoilEventQueryOptions", () => { + it("uses the current season and a one-day relative lookback when season is available", () => { + const latestBlock = 2_000_000n; + + expect(getSoilEventQueryOptions(latestBlock, 12_345)).toEqual({ + fromBlock: latestBlock - TIME_TO_BLOCKS.day, + toBlock: "latest", + args: { + season: 12_345, + }, + }); + }); + + it("uses latest-minus-one-month for fallback queries", () => { + const latestBlock = 2_000_000n; + + expect(getSoilEventQueryOptions(latestBlock)).toEqual({ + fromBlock: latestBlock - TIME_TO_BLOCKS.month, + toBlock: "latest", + }); + }); + + it("clamps low block numbers to zero", () => { + expect(getSoilEventQueryOptions(100n)).toEqual({ + fromBlock: 0n, + toBlock: "latest", + }); + + expect(getSoilEventQueryOptions(100n, 12_345)).toEqual({ + fromBlock: 0n, + toBlock: "latest", + args: { + season: 12_345, + }, + }); + }); +}); diff --git a/src/components/nav/nav/Navbar.tsx b/src/components/nav/nav/Navbar.tsx index aa4729fbe..8514da2dc 100644 --- a/src/components/nav/nav/Navbar.tsx +++ b/src/components/nav/nav/Navbar.tsx @@ -5,7 +5,6 @@ import HelperLink, { hoveredIdAtom } from "@/components/HelperLink"; import NoBaseValueAlert from "@/components/NoBaseValueAlert"; import { ScrollHideComponent } from "@/components/ScrollHideComponent"; import Panel from "@/components/ui/Panel"; -import useFarmerActions from "@/hooks/useFarmerActions"; import useFarmerStatus from "@/hooks/useFarmerStatus"; import { NavbarPanelType, navbarPanelAtom } from "@/state/app/navBar.atoms"; import { useFarmerBalances } from "@/state/useFarmerBalances"; @@ -43,7 +42,6 @@ const Navbar = () => { const queryClient = useQueryClient(); const account = useAccount(); - const farmerActions = useFarmerActions(); const farmerBalances = useFarmerBalances(); const priceData = usePriceData(); const farmerSilo = useFarmerSilo(); @@ -54,9 +52,7 @@ const Navbar = () => { const { refetch: refetchTwaDeltaBLP, queryKey: TwaDeltaBLPQuery } = useTwaDeltaBLPQuery(); const { refetch: refetchTwaDeltaB } = useTwaDeltaBQuery(); - const hasInternal = farmerActions.totalValue.wallet.internal.gt(0); - const floodValue = farmerActions.floodAssets.totalValue; - const usdValue = farmerActions.totalValue.wallet.total; + const hasFloodAssets = farmerSilo.flood.farmerSops.some((sop) => sop.wellsPlenty.plenty.gt(0)); const isHome = useMatch("/"); const isOverview = useMatch("/overview"); @@ -116,7 +112,7 @@ const Navbar = () => { return; } - if (floodValue.gt(0)) { + if (hasFloodAssets) { setPanelState({ ...panelState, openPanel: "wallet", @@ -128,10 +124,13 @@ const Navbar = () => { showTransfer: false, }, }); + return; } + togglePanel("wallet"); }, [ account.address, + hasFloodAssets, modal, panelState, @@ -272,18 +271,7 @@ const Navbar = () => { 0; + const lookbackBlocks = hasCurrentSeason ? TIME_TO_BLOCKS.day : TIME_TO_BLOCKS.month; + const safeLatestBlock = latestBlockNumber ?? 0n; + const fromBlock = safeLatestBlock > lookbackBlocks ? safeLatestBlock - lookbackBlocks : 0n; + + if (hasCurrentSeason) { + return { + fromBlock, + toBlock: "latest", + args: { + season: currentSeason, + }, + }; + } + + return { + fromBlock, + toBlock: "latest", + }; +} diff --git a/src/lib/Tractor/sowOrder/tractor-sow.ts b/src/lib/Tractor/sowOrder/tractor-sow.ts index 83c5e2aaa..3a1967dce 100644 --- a/src/lib/Tractor/sowOrder/tractor-sow.ts +++ b/src/lib/Tractor/sowOrder/tractor-sow.ts @@ -12,7 +12,6 @@ import { SOW_BLUEPRINT_V0_SELECTOR, TRACTOR_HELPERS_ADDRESS, } from "@/constants/address"; -import { TIME_TO_BLOCKS } from "@/constants/blocks"; import { PODS } from "@/constants/internalTokens"; import { beanstalkAbi } from "@/generated/contractHooks"; import { TRACTOR_DEPLOYMENT_BLOCK } from "@/lib/Tractor/core/constants"; @@ -27,6 +26,7 @@ import { generateBatchSortDepositsCallData } from "../../claim/depositUtils"; import { CreateTractorDataReturnType, WithdrawalPlan, decodeEncodedTractorDataToAdvancedPipeCalls } from "../core"; import { loadPublishedRequisitions } from "../requisitions/tractor-requisition"; import { LowStalkDepositsMode, WithdrawalPlanFilterParams } from "./../core/shared-tractor-types"; +import { getSoilEventQueryOptions } from "./soil-event-query"; import { OrderbookEntry, SowBlueprintData, SowBlueprintDisplayData, TractorSowOrderParams } from "./tractor-sow-types"; // ──────────────────────────────────────────────────────────────────────────────── @@ -440,6 +440,7 @@ export function decodeSowTractorData( export interface LoadOrderbookDataOptions { filterOutCompleted?: boolean; + currentSeason?: number; } export async function loadOrderbookData( @@ -454,7 +455,7 @@ export async function loadOrderbookData( ): Promise { if (!protocolAddress || !publicClient) return []; - const loadOptions: Required = { filterOutCompleted: true, ...options }; + const loadOptions = { filterOutCompleted: true, ...options }; const knownBlueprintHashes = new Set( activeApiEntries?.map((order) => order.requisition.blueprintHash.toLowerCase()) ?? [], @@ -808,12 +809,12 @@ export async function loadOrderbookData( // Get the total amount of soil available from the protocol try { // Query for the most recent Soil event + const soilQueryOptions = getSoilEventQueryOptions(latestBlock?.number, loadOptions.currentSeason); const soilEvents = await publicClient.getContractEvents({ address: protocolAddress, abi: diamondABI, eventName: "Soil", - fromBlock: TIME_TO_BLOCKS.month, - toBlock: "latest", + ...soilQueryOptions, }); // Get the most recent event (should be the last one) diff --git a/src/state/queryKeys.ts b/src/state/queryKeys.ts index 85846e6b2..f040966c4 100644 --- a/src/state/queryKeys.ts +++ b/src/state/queryKeys.ts @@ -60,6 +60,7 @@ const tractorQueryKeys = { options?: { cancelled?: boolean; filterOutCompleted?: boolean; + currentSeason?: number; }, ) => [ BASE_QKS.tractor, @@ -67,6 +68,7 @@ const tractorQueryKeys = { "chain", lastUpdatedBlock?.toString() ?? "0", maxTemp?.blockchainString ?? "0", + `season-${options?.currentSeason ?? "none"}`, `filter-completed-${Number(options?.filterOutCompleted ?? true)}`, `cancelled-${Number(options?.cancelled ?? "any")}`, ], diff --git a/src/state/tractor/useTractorSowOrders.ts b/src/state/tractor/useTractorSowOrders.ts index 76ef7b158..3a7cb0eee 100644 --- a/src/state/tractor/useTractorSowOrders.ts +++ b/src/state/tractor/useTractorSowOrders.ts @@ -7,6 +7,7 @@ import { OrderbookEntry, TractorAPI, TractorAPIOrdersResponse, loadOrderbookData import { TEMPERATURE_DECIMALS } from "@/state/protocol/field"; import { queryKeys } from "@/state/queryKeys"; import { useTemperature } from "@/state/useFieldData"; +import { useSeason } from "@/state/useSunData"; import { getChainConstant } from "@/utils/chain"; import { resolveChainId } from "@/utils/chain"; import { HashString } from "@/utils/types.generic"; @@ -150,6 +151,7 @@ export function useTractorSowOrderbook({ const client = usePublicClient({ chainId }); const diamond = useProtocolAddress(); const temperature = useTemperature(); + const currentSeason = useSeason(); // Deconstructed args const { address, chainOnly = false, enabled = true } = params; @@ -182,7 +184,10 @@ export function useTractorSowOrderbook({ ); const ordersChainQuery = useQuery({ - queryKey: queryKeys.tractor.sowOrdersV0Chain(orders?.lastUpdated ?? chainOnly ? 1 : 0, temperature.max, params), + queryKey: queryKeys.tractor.sowOrdersV0Chain(orders?.lastUpdated ?? chainOnly ? 1 : 0, temperature.max, { + ...params, + currentSeason, + }), queryFn: async () => { if (temperature.max.lte(0) || !client) { return []; @@ -203,7 +208,7 @@ export function useTractorSowOrderbook({ temperature.max.toNumber(), orders?.orders, lookbackBlocks, - params, + { ...params, currentSeason }, ); console.debug("[TRACTOR/useTractorSowOrderbook/ordersChainQuery] DATA", { diff --git a/src/state/use3PSiloWrappedTokenData.ts b/src/state/use3PSiloWrappedTokenData.ts index 96b1ff480..2dbada478 100644 --- a/src/state/use3PSiloWrappedTokenData.ts +++ b/src/state/use3PSiloWrappedTokenData.ts @@ -1,4 +1,5 @@ import { TokenValue } from "@/classes/TokenValue"; +import { defaultQuerySettings } from "@/constants/query"; import { CREAM_S_MAIN_TOKEN } from "@/constants/tokens"; import { useChainConstant } from "@/utils/chain"; import { useReadContract } from "wagmi"; @@ -26,6 +27,7 @@ export const useCreamSiloWrappedTokenExchangeRate = () => { abi: creamABISnippet, functionName: "exchangeRateStored", query: { + ...defaultQuerySettings, select: select, }, }); diff --git a/src/state/useFarmerSilo.ts b/src/state/useFarmerSilo.ts index ba2bc29e8..13b81e4e2 100644 --- a/src/state/useFarmerSilo.ts +++ b/src/state/useFarmerSilo.ts @@ -273,6 +273,7 @@ export function useFarmerSilo(address?: `0x${string}`, shouldLog?: boolean) { functionName: "balanceOfStalk", args: [farmerAddress ?? ZERO_ADDRESS], query: { + ...QUERY_SETTINGS, enabled: Boolean(farmerAddress), select: (data) => TokenValue.fromBlockchain(data ?? 0n, STALK.decimals), }, @@ -284,6 +285,7 @@ export function useFarmerSilo(address?: `0x${string}`, shouldLog?: boolean) { functionName: "balanceOfEarnedBeans", args: [farmerAddress ?? ZERO_ADDRESS], query: { + ...QUERY_SETTINGS, enabled: Boolean(farmerAddress), select: (data) => TokenValue.fromBlockchain(data ?? 0n, BEAN.decimals), },