feat: use arbitrum staking duration unchained endpoint - #11098
Conversation
📝 WalkthroughWalkthroughEnvironment variables for Arbitrum endpoints were updated from production to development hosts. The RFOX staking query logic was refactored from client-side blockchain log processing to a provider-based HTTP API call approach, with related files removed. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Hook as useTimeInPoolQuery
participant Provider as HTTP Provider
participant API as getRfoxStakingDuration<br/>(Backend API)
rect rgb(200, 220, 255)
note over User,API: NEW: Provider-Based Flow
User->>Hook: Request time in pool
Hook->>Provider: Get EVM chain adapter
activate Provider
Provider-->>Hook: Chain adapter (HTTP)
deactivate Provider
Hook->>API: Call getRfoxStakingDuration<br/>(staking account, contract)
activate API
API-->>Hook: Staking duration (ms)
deactivate API
Hook->>Hook: Convert to BigInt result
Hook-->>User: Time in pool (BigInt)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/pages/RFOX/hooks/useTimeInPoolQuery.ts (1)
54-64: Consider explicit error handling and documenting the 0 fallback.The query function lacks explicit error handling and uses a silent fallback to
0when the staking duration is not found.Consider these improvements:
- Error handling: While React Query will catch thrown errors, consider adding explicit logging for debugging
- Document fallback: The
?? 0fallback might hide cases where the contract is not found in the responseApply this diff:
return async () => { const stakingDuration = await provider.getRfoxStakingDuration({ address: fromAccountId(stakingAssetAccountId).account, }) - - return BigInt(stakingDuration[getStakingContract(stakingAssetId)] ?? 0) + + const contract = getStakingContract(stakingAssetId) + const duration = stakingDuration[contract] + + // Note: Returns 0 for newly staked users until cache refreshes (up to 15 min) + if (duration === undefined) { + console.debug(`No staking duration found for contract ${contract}`) + } + + return BigInt(duration ?? 0) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
.env.private(1 hunks).env.production(1 hunks)src/pages/RFOX/hooks/useAccountLogsQuery.ts(0 hunks)src/pages/RFOX/hooks/useTimeInPoolQuery.test.ts(0 hunks)src/pages/RFOX/hooks/useTimeInPoolQuery.ts(2 hunks)
💤 Files with no reviewable changes (2)
- src/pages/RFOX/hooks/useTimeInPoolQuery.test.ts
- src/pages/RFOX/hooks/useAccountLogsQuery.ts
🧰 Additional context used
🧬 Code graph analysis (1)
src/pages/RFOX/hooks/useTimeInPoolQuery.ts (4)
packages/caip/src/assetId/assetId.ts (1)
AssetId(17-17)src/lib/utils/evm/index.ts (1)
assertGetEvmChainAdapter(185-194)packages/caip/src/constants.ts (1)
arbitrumChainId(66-66)src/pages/RFOX/helpers.ts (1)
getStakingContract(50-54)
🪛 dotenv-linter (4.0.0)
.env.production
[warning] 24-24: [UnorderedKey] The VITE_UNCHAINED_ARBITRUM_HTTP_URL key should go before the VITE_UNCHAINED_AVALANCHE_HTTP_URL key
(UnorderedKey)
[warning] 25-25: [UnorderedKey] The VITE_UNCHAINED_ARBITRUM_WS_URL key should go before the VITE_UNCHAINED_AVALANCHE_HTTP_URL key
(UnorderedKey)
.env.private
[warning] 18-18: [UnorderedKey] The VITE_UNCHAINED_ARBITRUM_HTTP_URL key should go before the VITE_UNCHAINED_AVALANCHE_HTTP_URL key
(UnorderedKey)
[warning] 19-19: [UnorderedKey] The VITE_UNCHAINED_ARBITRUM_WS_URL key should go before the VITE_UNCHAINED_AVALANCHE_HTTP_URL key
(UnorderedKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Install and Cache
🔇 Additional comments (8)
.env.private (1)
18-19: Verify consistency with production endpoint changes.The dev endpoint configuration here is consistent with
.env.production. Since this is a private environment, the risk is lower than production, but ensure these are also reverted when production endpoints are switched back.src/pages/RFOX/hooks/useTimeInPoolQuery.ts (6)
1-9: LGTM! Imports align with provider-based refactor.The new imports support the shift from client-side log processing to the unchained API approach.
19-33: LGTM! Improved type safety.The function signature now requires explicit
AccountId | undefinedandAssetId | undefinedtypes instead of loose string types, improving type safety.
35-39: LGTM! Type definition aligns with provider-based approach.The updated type correctly reflects the new implementation requirements.
50-52: LGTM! Query key correctly memoized.Dependencies correctly track the inputs to the query key.
66-66: LGTM! Clean React Query integration.The hook correctly returns the query result with optional select transformation.
46-48: Verify stakingAssetId is always on Arbitrum.The provider is hardcoded to
arbitrumChainIdwithout validating thatstakingAssetIdbelongs to the Arbitrum chain. If stakingAssetId could be on a different chain, this will cause incorrect behavior.Run this script to verify all staking assets are on Arbitrum:
If staking assets can be on other chains, apply this diff to add validation:
const provider = useMemo(() => { + // Validate stakingAssetId is on Arbitrum + if (stakingAssetId && !stakingAssetId.startsWith('eip155:42161/')) { + throw new Error(`Staking asset ${stakingAssetId} must be on Arbitrum chain`) + } return assertGetEvmChainAdapter(arbitrumChainId).httpProvider as unchained.evm.arbitrum.V1Api -}, []) +}, [stakingAssetId]).env.production (1)
24-25: Verify the actual intent: dev-api.arbitrum change appears intentional, not temporary.The review comment claims the PR description states this is "temporary," but verification reveals this is a deliberate feature change, not a temporary deployment workaround:
- Commit type:
feat(feature, notfixorhotfix)- Significant code refactoring: 273 lines removed from useTimeInPoolQuery, 31 added
- Both
.env.productionand.env.privateupdated identically- Commit message focuses on "use arbitrum staking duration unchained endpoint" with no mention of temporary status
- No TODO or tracking comments present in either file
However, the concern about dev-api in production remains valid: VITE_ARBITRUM_NODE_URL still uses production (
api.arbitrum.shapeshift.com), creating mixed environment endpoints.Action needed: Confirm whether pointing VITE_UNCHAINED_ARBITRUM endpoints to dev-api is:
- An intentional architectural decision for the staking duration feature (appears likely based on code changes), or
- An accidental configuration that needs reverting to
api.arbitrum.shapeshift.comIf intentional, document why dev-api is appropriate for production; if unintentional, revert both env files to use production endpoints.

Description
Leverage new
/rfox/staking-durationendpoint exposed by unchained instead of calculating client side. This allows us to fully cut over arbitrum in web (without breaking rfox details). Note, the event log cache is updated every 15 minutes at this time. This means that for newly staked users or users that fully unstake, there will be some delay for theTime in Poolvalue to update.Update production and private to point to dev endpoint until everything is fully deployed and we can cut back to prod endpoints.
Issue (if applicable)
N/A
Risk
Low
Testing
Engineering
☝️
Operations
☝️
Screenshots (if applicable)
Summary by CodeRabbit
Chores
Refactor