Feature/recent escrow events#51
Conversation
- Implement useRecentEvents hook to fetch Soroban contract events via Stellar RPC - Add Recent Contract Events section in Transaction History view - Display events with type, ledger, ID, topics, and value (base64) - Handle loading, error, and empty states - Include disclosure about 7-day RPC limitation - Events ordered most recent first
|
@bitstarkbridge is attempting to deploy a commit to the Trustless Work Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughAdds a POST RPC proxy route and threads network selection across data-fetching utilities and UI, introduces a new useRecentEvents hook, updates escrow components for network-aware behavior and error handling, and adjusts network configuration and RPC call targets. Changes
Sequence Diagram(s)sequenceDiagram
participant Component as EscrowDetails
participant Hook as useRecentEvents
participant Proxy as /api/rpc (proxy)
participant StellarRPC as Stellar RPC
Component->>Hook: call useRecentEvents(contractId, network)
activate Hook
Hook->>Proxy: POST { method: "getLatestLedger", network }
activate Proxy
Proxy->>StellarRPC: getLatestLedger()
StellarRPC-->>Proxy: { endLedger }
Proxy-->>Hook: { endLedger }
deactivate Proxy
Note over Hook: compute startLedger (~7 days prior)
Hook->>Proxy: POST { method: "getEvents", params: { contractId, startLedger, endLedger }, network }
activate Proxy
Proxy->>StellarRPC: getEvents(filters)
StellarRPC-->>Proxy: events[]
Proxy-->>Hook: events[]
deactivate Proxy
Hook-->>Component: { events, loading, error, refetch }
deactivate Hook
sequenceDiagram
participant User as User
participant Component as EscrowDetails
participant Hook as useEscrowData
participant Proxy as /api/rpc (proxy)
User->>Component: open contractId view
Component->>Hook: useEscrowData(contractId, network)
activate Hook
Hook->>Hook: validate contractId (56-char base32)
alt invalid
Hook-->>Component: set error (invalid id)
else valid
Hook->>Proxy: POST { method: "getLedgerKeyContractCode", params:{contractId}, network }
activate Proxy
Proxy->>StellarRPC: getLedgerKeyContractCode(...)
StellarRPC-->>Proxy: data or empty
Proxy-->>Hook: data / []
deactivate Proxy
alt data found
Hook-->>Component: set data
else no data
Hook-->>Component: set contextual error (suggest network)
end
end
deactivate Hook
alt error shown
Component->>Component: render ErrorDisplay(error, onSwitchNetwork, onRetry)
User->>Component: click "Switch to Testnet/Mainnet"
Component-->>Hook: setNetwork(network) + refresh flows
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/escrow/TransactionDetailModal.tsx (1)
159-174: Inconsistent network usage in explorer links.Line 163 uses
process.env.NEXT_PUBLIC_STELLAR_NETWORK || 'testnet'for the explorer URL, while line 171 hardcodes'testnet'. Both should use thenetworkprop passed to this component for consistency.🔧 Proposed fix
<Button variant="ghost" size="sm" className="h-8 w-8 p-0" - onClick={() => window.open(`https://stellar.expert/explorer/${process.env.NEXT_PUBLIC_STELLAR_NETWORK || 'testnet'}/tx/${details.txHash}`, "_blank")} + onClick={() => copyToClipboard(details.txHash)} > <Copy className="h-4 w-4" /> </Button> <Button variant="ghost" size="sm" className="h-8 w-8 p-0" - onClick={() => window.open(`https://stellar.expert/explorer/testnet/tx/${details.txHash}`, "_blank")} + onClick={() => window.open(`https://stellar.expert/explorer/${network}/tx/${details.txHash}`, "_blank")} > <ExternalLink className="h-4 w-4" /> </Button>Note: The first button also appears to open an external link instead of copying—it should call
copyToClipboard(details.txHash)based on theCopyicon.src/components/escrow/EscrowDetails.tsx (1)
196-221: Remove or disable debug logging before merge.The
DEBUG = trueflag with multipleconsole.logstatements should be removed or disabled for production. Consider using a proper logging utility with environment-based log levels instead.🔧 Proposed fix
-// === DEBUG LOGGING (EscrowDetails) === -const DEBUG = true; - -useEffect(() => { - if (!DEBUG) return; - console.log("[DBG][EscrowDetails] network:", currentNetwork); - console.log("[DBG][EscrowDetails] contractId:", contractId); -}, [currentNetwork, contractId]); - -useEffect(() => { - if (!DEBUG) return; - console.log("[DBG][EscrowDetails] raw escrow map:", raw); -}, [raw]); - -useEffect(() => { - if (!DEBUG) return; - console.log("[DBG][EscrowDetails] organized data:", organized); -}, [organized]); - -useEffect(() => { - if (!DEBUG) return; - console.log("[DBG][EscrowDetails] token live balance:", { - ledgerBalance, - decimals, - mismatch, - }); -}, [ledgerBalance, decimals, mismatch]);
🤖 Fix all issues with AI agents
In `@src/components/escrow/error-display.tsx`:
- Around line 17-25: The network-switch detection in error-display.ts currently
looks for "Try switching to" (via parts.find -> switchSuggestion) so the switch
button never appears because useEscrowData.ts errors don't contain that phrase;
update the detection in error-display.ts to also match the actual messages
(e.g., check parts for substrings like "different network", "not be deployed",
or "contract exists on a different network") and map those matches to
targetNetwork ('testnet' | 'mainnet') accordingly, or alternatively add matching
"Try switching to testnet"/"Try switching to mainnet" suggestions in
useEscrowData.ts so the existing parts.find logic can succeed.
In `@src/hooks/useRecentEvents.ts`:
- Around line 91-105: The mappedEvents mapping in useRecentEvents.ts can set
topics to undefined when event.topic is missing; update the mapping in the
mappedEvents creation (the arrow mapping over eventsData.result?.events) to
ensure topics is always a string[] by replacing event.topic with a safe fallback
(e.g., event.topic ?? [] or Array.isArray(event.topic) ? event.topic : []) so
that ContractEvent.topics is never undefined.
- Around line 51-52: Check and handle malformed RPC responses before accessing
nested fields: after awaiting latestLedgerResponse.json() verify
latestLedgerResponse.ok and that latestLedgerData and latestLedgerData.result
exist and that latestLedgerData.result.sequence is a valid number; if any check
fails, handle gracefully (return early, set endLedger to null/undefined, or
throw a descriptive error) instead of directly using
latestLedgerData.result.sequence. Update the logic around latestLedgerResponse,
latestLedgerData and endLedger in useRecentEvents.ts to include these null/ok
checks and a clear fallback path.
🧹 Nitpick comments (2)
src/hooks/useRecentEvents.ts (1)
54-56: Consider documenting the ledger calculation.The ~5 seconds per ledger assumption is reasonable for Stellar, but this value can vary. A brief inline comment noting this is an approximation would help future maintainers.
src/components/escrow/error-display.tsx (1)
38-45: Consider using a stable key instead of index.Using
indexas a React key works here since the error list is static and won't reorder, but a stable key derived from content would be slightly better.- {parts.slice(1).map((line, index) => ( - <li key={index}>{line}</li> + {parts.slice(1).map((line) => ( + <li key={line}>{line}</li> ))}
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/lib/network-config.ts (1)
29-31: Return a default network value (or remove the export).This function currently returns
undefined, violating the declared return type and breaking callers at runtime/compile time.🛠️ Proposed fix
export function getDefaultNetwork(): NetworkType { - + return 'testnet'; }src/components/escrow/EscrowDetails.tsx (1)
13-13: Build break:getStellarLabUrlis no longer exported.
getStellarLabUrlwas removed fromsrc/lib/network-config.ts, so this import/usage will fail. Either restore the helper or replace it with the new URL-building approach.Also applies to: 294-296
🤖 Fix all issues with AI agents
In `@src/components/ui/theme-toggle.tsx`:
- Around line 6-18: The ThemeToggle component is missing state and theme-apply
logic: declare state like isDark and setIsDark (via useState) and a mounted flag
(via useState/useEffect) inside ThemeToggle, restore the first useEffect to
initialize isDark from persisted preference (e.g., localStorage or
window.matchMedia) and set mounted=true, implement the second useEffect to
add/remove the theme class on document.documentElement based on isDark and
mounted, and update the toggle handler to call setIsDark and persist the new
preference; use the symbols ThemeToggle, isDark, setIsDark, mounted, toggle, and
the two useEffect blocks to place these fixes.
🧹 Nitpick comments (1)
src/components/escrow/EscrowDetails.tsx (1)
33-36: Consider deferring recent-events RPC until the panel is shown.
useRecentEventsruns on every page load, even when the Recent Contract Events panel is hidden, adding extra RPC calls. Consider adding anenabledflag or gating byshowOnlyTransactionsto reduce load.Also applies to: 82-87, 382-458
#43 close
Summary by CodeRabbit
New Features
Bug Fixes
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.