Repository navigation
feat: Deposit refunds for foreclosed applications - #484
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@copilot review this PR for bugs |
Bug (medium): |
There was a problem hiding this comment.
🟡 Changes recommended
Refund discovery can omit eligible deposits, missing epoch data can expose invalid offers, and failed simulations cannot be retried through the button.
3 open issues
What changed in this PR
Adds permissionless deposit refunds to the explorer for foreclosed applications, using on-chain refund status while preserving the node’s existing data flow.
Changes:
- Adds refund discovery, asset metadata, status displays, transaction actions, and summary counters.
- Integrates refunds into application summaries and epoch pages, and makes summary counters collapsible.
- Extracts the shared transaction sender and adds refund fixtures, stories, and tests.
| File | Description |
|---|---|
| apps/explorer/test/page/EpochPage.test.tsx | Tests foreclosure-based refund visibility. |
| apps/explorer/test/page/ApplicationSummaryPage.test.tsx | Tests refund displays and refresh callbacks. |
| apps/explorer/test/lib/contractErrors.test.ts | Tests revert and wallet-rejection helpers. |
| apps/explorer/test/components/transactions/hooks/useTransactionSender.test.tsx | Tests wallet and network guards. |
| apps/explorer/test/components/refund/RefundDepositView.test.tsx | Tests refund states and asset displays. |
| apps/explorer/test/components/refund/RefundDepositAction.test.tsx | Tests refund transaction behavior. |
| apps/explorer/test/components/refund/RefundableDeposits.test.tsx | Tests table contents and links. |
| apps/explorer/test/components/refund/lib/refundUtils.test.ts | Tests decoding, formatting, and eligibility helpers. |
| apps/explorer/test/components/refund/hooks/useRefundStatus.test.tsx | Tests individual and batched status reads. |
| apps/explorer/test/components/refund/hooks/useRefundAssets.test.tsx | Tests token metadata enrichment. |
| apps/explorer/test/components/refund/hooks/useRefundableDeposits.test.tsx | Tests deposit discovery and filtering. |
| apps/explorer/test/components/refund/hooks/useIssuedRefundCount.test.tsx | Tests refund count reads. |
| apps/explorer/test/components/input/InputList.test.tsx | Tests refund action integration. |
| apps/explorer/test/components/application/SummaryCards.test.tsx | Tests counter expansion and collapse. |
| apps/explorer/src/stories/refunds.ts | Adds refund fixtures and mocked chain reads. |
| apps/explorer/src/stories/deposits.ts | Adds encoded portal deposit fixtures. |
| apps/explorer/src/page/EpochPage.tsx | Supplies application and epoch context to inputs. |
| apps/explorer/src/page/EpochPage.stories.tsx | Adds foreclosed epoch scenarios. |
| apps/explorer/src/page/ApplicationSummaryPage.tsx | Integrates refunds and collapsible counters. |
| apps/explorer/src/page/ApplicationSummaryPage.stories.tsx | Adds a refundable-deposit scenario. |
| apps/explorer/src/lib/contractErrors.ts | Adds contract error inspection helpers. |
| apps/explorer/src/content/refundMessages.ts | Defines refund labels and error copy. |
| apps/explorer/src/content/index.ts | Exposes refund messages. |
| apps/explorer/src/content/globalMessages.ts | Adds counter controls and shared copy. |
| apps/explorer/src/containers/ApplicationSummaryContainer.tsx | Connects refund data and refresh callbacks. |
| apps/explorer/src/components/transactions/hooks/useTransactionSender.ts | Extracts the shared transaction guard. |
| apps/explorer/src/components/tournament/InnerTournamentAction.tsx | Uses the extracted transaction guard. |
| apps/explorer/src/components/refund/RefundDepositView.tsx | Displays refund assets, actions, and states. |
| apps/explorer/src/components/refund/RefundDepositView.stories.ts | Covers refund display scenarios. |
| apps/explorer/src/components/refund/RefundDepositAction.tsx | Implements simulation, submission, and confirmation. |
| apps/explorer/src/components/refund/RefundDepositAction.stories.ts | Adds actionable and refunded scenarios. |
| apps/explorer/src/components/refund/RefundableDeposits.tsx | Displays the latest refundable deposits. |
| apps/explorer/src/components/refund/RefundableDeposits.stories.ts | Demonstrates the refund table. |
| apps/explorer/src/components/refund/lib/refundUtils.ts | Adds deposit, asset, and status helpers. |
| apps/explorer/src/components/refund/hooks/useRefundStatus.ts | Reads refund flags on chain. |
| apps/explorer/src/components/refund/hooks/useRefundAssets.ts | Batches and caches token metadata reads. |
| apps/explorer/src/components/refund/hooks/useRefundableDeposits.ts | Discovers deposits across portal senders. |
| apps/explorer/src/components/refund/hooks/useIssuedRefundCount.ts | Reads the issued-refund count. |
| apps/explorer/src/components/match/MatchTimeoutAction.tsx | Uses the extracted transaction guard. |
| apps/explorer/src/components/input/InputList.tsx | Adds refund actions to input cards. |
| apps/explorer/src/components/input/InputCard.tsx | Adds a footer slot for refund content. |
| apps/explorer/src/components/input/InputCard.stories.tsx | Demonstrates a refund footer. |
| apps/explorer/src/components/dispute/DisputeAction.tsx | Removes the extracted sender hook. |
| apps/explorer/src/components/application/SummaryCards.tsx | Adds responsive, collapsible counters. |
| apps/explorer/src/components/application/SummaryCards.stories.ts | Demonstrates counter layouts and states. |
| apps/explorer/src/components/application/SummaryCards.module.css | Styles the counter fade and expansion control. |
Review effort: Balanced
68fddd0 to
4eefe41
Compare

Summary
Offer refunds of portal deposits on foreclosed applications, through the permissionless
IApplication.issueRefundcontract call. The node does not index refunds, so the explorer reads each deposit's refund flag on chain and keeps the rest of the data flow unchanged.A deposit is refundable when the application is foreclosed and its input sits in an epoch after the last accepted one. Anyone can issue the refund: the contract pays the original depositor and the caller only pays gas.
Refunds
getNumberOfIssuedRefunds.symbolanddecimalsare read on chain in one batched call per distinct token and cached, so amounts render as250 USDCrather than raw units; a token without metadata falls back to units and its address.RefundAlreadyIssued,InsufficientFunds), the token's own revert reason when there is one, and a generic fallback. A wallet rejection simply returns the button to its previous state.Metarefetch, with no block polling.Summary counters
Components, hooks & helpers
Addresskeeps its icon and text on a single line when givenwrap="nowrap", instead of wrapping or breaking the address; callers that pass nothing are unchanged.useDisputeSenderrenamed touseTransactionSender, since it now guards every permissionless write, not only disputes.getRevertErrorName,getRevertReasonandisUserRejectionhelpers over viem errors.Testing
Components/Refund, including a phone-width table, plus foreclosed scenarios on the epoch details and application summary pages, backed by a shared MSW handler that answers the refund reads.Manual check on a local devnet with the Cartesi CLI:
cartesi createcartesi.tomlwith the guardian as an account you controlcartesi build→cartesi runcartesi depositether, ERC-20, ERC-721, ERC-1155)Then: