Skip to content

Conversation

@bordalix
Copy link
Collaborator

@bordalix bordalix commented Oct 23, 2025

@tiero @Kukks please review

Summary by CodeRabbit

  • New Features
    • Transaction details now display expiry information.
    • Added visual indicators for preconfirmed transactions with orange color coding.
    • Transaction status now shows "Pending boarding" state for boarding transactions.
    • Boarding UTXOs are now displayed alongside virtual coins with expiration details.
    • Transaction action labels now reflect boarding status ("Complete boarding" vs "Settle transaction").

@bordalix bordalix requested a review from Copilot October 23, 2025 08:16
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR modifies the VTXO (Virtual Transaction Output) display functionality to show subdust coins that were previously filtered out. The change retrieves all VTXOs including recoverable ones, rather than only displaying spendable VTXOs above the dust threshold.

Key changes:

  • Fetches all VTXOs (including recoverable ones) instead of only spendable VTXOs
  • Updates the display logic to show unspent VTXOs regardless of dust threshold
  • Adds type casting for wallet parameter consistency

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/screens/Settings/Vtxos.tsx Adds fetching of all VTXOs including recoverable ones, updates display logic to show all unspent coins instead of only spendable ones
src/lib/vtxo.ts Adds type cast to ServiceWorkerWallet for wallet parameter in getVtxos call

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Your virtual coins with amount and expiration
</Text>
{vtxos.spendable?.map((v: Vtxo) => (
{listableVtxos.map((v: ExtendedVirtualCoin) => (
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The VtxoLine component expects a Vtxo type parameter but is now receiving ExtendedVirtualCoin. This type mismatch could cause runtime errors if the properties differ between these types. Update VtxoLine's type signature to accept ExtendedVirtualCoin or ensure the types are compatible.

Suggested change
{listableVtxos.map((v: ExtendedVirtualCoin) => (
{listableVtxos.map((v) => (

Copilot uses AI. Check for mistakes.
const getOrphanVtxos = async (wallet: IWallet): Promise<ExtendedVirtualCoin[]> => {
const now = Date.now()
const { spendable } = await getVtxos(wallet)
const { spendable } = await getVtxos(wallet as ServiceWorkerWallet)
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a type cast suggests that the function signature should be updated instead. Consider changing the getOrphanVtxos function parameter type from IWallet to ServiceWorkerWallet, or update getVtxos to accept IWallet if it should support the broader interface.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems to me getVtxos may take the interface ?

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Oct 23, 2025

Deploying wallet-signet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3fb377c
Status: ✅  Deploy successful!
Preview URL: https://436922cb.wallet-23u.pages.dev
Branch Preview URL: https://show-subdust-coins.wallet-23u.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Oct 23, 2025

Deploying wallet-mutinynet with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3fb377c
Status: ✅  Deploy successful!
Preview URL: https://89b96a80.arkade-wallet.pages.dev
Branch Preview URL: https://show-subdust-coins.arkade-wallet.pages.dev

View logs

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Oct 23, 2025

Deploying wallet-bitcoin with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3fb377c
Status: ✅  Deploy successful!
Preview URL: https://1c6fef02.wallet-bitcoin.pages.dev
Branch Preview URL: https://show-subdust-coins.wallet-bitcoin.pages.dev

View logs

import { maxPercentage } from './constants'
import { getVtxos } from './asp'

// this should never happen, but just in case
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: why should never happen ?

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 23, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

The PR extends transaction and VTXO UI to support expiry fields, adds preconfirmed boarding status visualization, narrows wallet typing to ServiceWorkerWallet in VTXO retrieval, and enhances the Vtxos screen to display both virtual coins and boarding UTXOs with expiry information.

Changes

Cohort / File(s) Summary
Details & Transaction List Components
src/components/Details.tsx, src/components/TransactionsList.tsx
Added expiry field display to Details component; extended TransactionsList to show PreconfirmedIcon and orange coloring for preconfirmed boarding transactions
Transaction Screen
src/screens/Wallet/Transaction.tsx
Added boarding state handling with "Pending boarding" status, boarding exit delay logic, and conditional "Complete boarding" button label based on boarding state
VTXO Library & Management
src/lib/vtxo.ts, src/screens/Settings/Vtxos.tsx
Narrowed wallet typing to ServiceWorkerWallet in getOrphanVtxos; enhanced Vtxos screen to fetch and display both virtual coins and boarding UTXOs with expiry, tags, and reusable CoinLine component

Sequence Diagram

sequenceDiagram
    participant User
    participant TransactionScreen as Transaction<br/>Screen
    participant State as App State
    
    User->>TransactionScreen: View transaction
    TransactionScreen->>State: Check tx.boardingTx & preconfirmed
    
    alt Pending Boarding
        State-->>TransactionScreen: Not settled + boarding exists
        TransactionScreen->>TransactionScreen: Show "Pending boarding" status
        TransactionScreen->>TransactionScreen: Check expiry: elapsed > boardingExitDelay
        Note over TransactionScreen: If expired → mark as expired boarding
        TransactionScreen->>User: Render "Complete boarding" button
    else Settled or Preconfirmed
        State-->>TransactionScreen: Return settled/preconfirmed state
        TransactionScreen->>User: Render "Settle transaction" button
    end
    
    TransactionScreen->>User: Display transaction with expiry field & Info block
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

The diff involves heterogeneous changes across five files with varying complexity. Transaction.tsx contains logic-dense boarding state determination and expiry timing logic. Vtxos.tsx introduces significant structural refactoring with new component composition and data collection flows. VTXO library changes include type narrowing that affects retrieval logic. UI component changes are more straightforward but require coordination understanding.

Possibly related PRs

Suggested reviewers

  • tiero
  • louisinger

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Show subdust coins" is partially related to the changeset. It accurately refers to a real and significant aspect of the changes—specifically the subdust tag introduced in the Vtxos.tsx file for rendering coins with various categorization tags. However, the title does not fully capture the scope of the pull request, which also includes substantial changes to handle boarding transaction status, expiry field display in the Details component, preconfirmed indicators in the TransactionsList, and boarding-related timing logic in the Transaction screen. The title highlights one important aspect but is somewhat narrower than the overall objective of the PR.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch show_subdust_coins

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/screens/Wallet/Transaction.tsx (1)

170-172: Remove || true from the disabled prop—resend functionality must be implemented per the TODO at line 81.

The button is permanently disabled due to disabled={resending || true}. Line 81 contains // TODO implement resend, confirming this is placeholder code. When implementing the resend logic, remove || true so the button respects the resending state variable: disabled={resending}.

♻️ Duplicate comments (1)
src/lib/vtxo.ts (1)

5-5: Clarify or remove “this should never happen” comment.

Explain under which conditions “orphan VTXOs” might occur, or remove the comment to avoid confusion.

🧹 Nitpick comments (5)
src/lib/vtxo.ts (1)

1-1: Avoid unsafe cast; widen getVtxos to IWallet and drop the import.

Casting wallet as ServiceWorkerWallet is unnecessary if getVtxos only calls wallet.getVtxos(). Prefer updating getVtxos to accept IWallet, then remove the cast and the now‑unused ServiceWorkerWallet import here. This improves type safety and aligns with our prior guidance to keep wallet APIs IWallet‑based. Based on learnings.

Apply locally:

-import { ExtendedVirtualCoin, IWallet, ServiceWorkerWallet, VtxoManager } from '@arkade-os/sdk'
+import { ExtendedVirtualCoin, IWallet, VtxoManager } from '@arkade-os/sdk'
-  const { spendable } = await getVtxos(wallet as ServiceWorkerWallet)
+  const { spendable } = await getVtxos(wallet)

And in src/lib/asp.ts (external to this diff), adjust signature:

// before
export const getVtxos = async (wallet: ServiceWorkerWallet) => {
// after
export const getVtxos = async (wallet: IWallet) => {

Also applies to: 8-8

src/components/TransactionsList.tsx (1)

28-35: Minor readability: factor a single boolean for preconfirmed boarding.

You repeat tx.preconfirmed && tx.boardingTxid. Consider:

+  const isPreconfirmedBoarding = Boolean(tx.preconfirmed && tx.boardingTxid)
   const Fiat = () => {
-    const color =
+    const color =
       config.currencyDisplay === CurrencyDisplay.Both
         ? 'dark50'
         : tx.type === 'received'
           ? 'green'
-          : tx.boardingTxid && tx.preconfirmed
+          : isPreconfirmedBoarding
             ? 'orange'
             : ''
-  const Icon = () => tx.type === 'sent' ? <SentIcon /> : tx.preconfirmed && tx.boardingTxid ? <PreconfirmedIcon /> : <ReceivedIcon />
+  const Icon = () => tx.type === 'sent' ? <SentIcon /> : isPreconfirmedBoarding ? <PreconfirmedIcon /> : <ReceivedIcon />
-  <Text color={tx.type === 'received' ? (tx.preconfirmed && tx.boardingTxid ? 'orange' : 'green') : ''} thin>
+  <Text color={tx.type === 'received' ? (isPreconfirmedBoarding ? 'orange' : 'green') : ''} thin>

Also applies to: 50-50

src/screens/Wallet/Transaction.tsx (2)

36-41: Harden expiry-time calculation and button label updates.

  • Use integer seconds to avoid fractional comparisons.
  • Ensure the button label reacts if the boarding state changes.
-const defaultButtonLabel = boardingTx ? 'Complete boarding' : 'Settle transaction'
-const boardingExitDelay = Number(aspInfo?.boardingExitDelay || 0)
+const defaultButtonLabel = boardingTx ? 'Complete boarding' : 'Settle transaction'
+const boardingExitDelay = Number(aspInfo?.boardingExitDelay || 0)

-const expiredBoardingTx =
-  !tx?.settled && boardingTx && tx?.createdAt && Date.now() / 1000 - tx?.createdAt > boardingExitDelay
+const nowSec = Math.floor(Date.now() / 1000)
+const expiredBoardingTx =
+  !tx?.settled && boardingTx && tx?.createdAt && nowSec - tx.createdAt > boardingExitDelay

And a matching effect tweak (near Lines 53‑55):

-useEffect(() => {
-  setButtonLabel(settling ? 'Settling...' : defaultButtonLabel)
-}, [settling])
+useEffect(() => {
+  setButtonLabel(settling ? 'Settling...' : defaultButtonLabel)
+}, [settling, defaultButtonLabel])

139-142: Copy nit: “Onboarding” instead of “Onboard”.

Minor grammar fix in the info box title/body.

-<Info color='orange' icon={<VtxosIcon />} title='Pending boarding'>
-  <Text wrap>Onboard transaction confirmed on-chain.</Text>
+<Info color='orange' icon={<VtxosIcon />} title='Pending onboarding'>
+  <Text wrap>Onboarding transaction confirmed on-chain.</Text>
src/screens/Settings/Vtxos.tsx (1)

190-201: Consistency: show “Unknown” expiry when block time is missing.

VtxoLine shows 'Unknown' when expiry is not available; mirror that in UtxoLine.

-  const expiry = utxo.status.block_time ? prettyAgo(utxo.status.block_time + expiration) : ''
+  const expiry = utxo.status.block_time ? prettyAgo(utxo.status.block_time + expiration) : 'Unknown'
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a609cca and 3fb377c.

📒 Files selected for processing (5)
  • src/components/Details.tsx (3 hunks)
  • src/components/TransactionsList.tsx (3 hunks)
  • src/lib/vtxo.ts (1 hunks)
  • src/screens/Settings/Vtxos.tsx (6 hunks)
  • src/screens/Wallet/Transaction.tsx (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-30T18:33:29.839Z
Learnt from: bordalix
PR: arkade-os/wallet#114
File: src/lib/asp.ts:0-0
Timestamp: 2025-06-30T18:33:29.839Z
Learning: In src/lib/asp.ts, only the collaborativeExit function should accept both IWallet and ServiceWorkerWallet types. Other wallet functions (getBalance, getTxHistory, getReceivingAddresses, redeemNotes, sendOnChain, settleVtxos) should maintain their original IWallet-only signatures and not be updated for consistency.

Applied to files:

  • src/lib/vtxo.ts
🧬 Code graph analysis (5)
src/components/Details.tsx (1)
src/icons/Date.tsx (1)
  • DateIcon (1-13)
src/lib/vtxo.ts (1)
src/lib/asp.ts (1)
  • getVtxos (124-135)
src/screens/Settings/Vtxos.tsx (6)
src/lib/logs.ts (1)
  • consoleError (40-44)
src/components/Text.tsx (1)
  • Text (25-79)
src/components/FlexRow.tsx (1)
  • FlexRow (16-45)
src/lib/types.ts (1)
  • Vtxo (95-95)
src/lib/format.ts (3)
  • prettyNumber (85-88)
  • prettyHide (69-74)
  • prettyAgo (12-25)
src/components/Empty.tsx (1)
  • EmptyCoinsList (26-34)
src/screens/Wallet/Transaction.tsx (3)
src/components/Info.tsx (1)
  • Info (14-30)
src/icons/Vtxos.tsx (1)
  • VtxosIcon (1-13)
src/components/Text.tsx (1)
  • Text (25-79)
src/components/TransactionsList.tsx (4)
src/icons/Sent.tsx (1)
  • SentIcon (1-13)
src/icons/Preconfirmed.tsx (1)
  • PreconfirmedIcon (1-12)
src/icons/Received.tsx (1)
  • ReceivedIcon (1-13)
src/components/Text.tsx (2)
  • Text (25-79)
  • TextSecondary (91-97)
🪛 Biome (2.1.2)
src/components/TransactionsList.tsx

[error] 48-48: Do not shadow the global "Date" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🔇 Additional comments (3)
src/components/Details.tsx (1)

23-23: Expiry support looks good; ensure consistent formatting.

The new expiry field and row render are fine. Please confirm callers always provide a preformatted string (e.g., prettyDate/prettyAgo) to avoid mixed formats.

Also applies to: 40-55, 74-74

src/components/TransactionsList.tsx (1)

45-46: Confirm intent: Preconfirmed icon only for received transactions.

Current logic renders SentIcon for all sent txs, even if preconfirmed && boardingTxid. Should sent preconfirmed/boarding txs show a special icon or color as well?

src/screens/Settings/Vtxos.tsx (1)

127-148: Tags and lines look solid.

Good separation via CoinLine and consistent tags (subdust/settled/swept/unconfirmed). Expiry math for VTXOs uses ms and is handled by prettyAgo correctly; UTXOs use seconds + delay—looks right.

Please confirm aspInfo.dust and boardingExitDelay are in sats/seconds respectively across providers.

Also applies to: 177-188

const Icon = () =>
tx.type === 'sent' ? <SentIcon /> : tx.preconfirmed && tx.boardingTxid ? <PreconfirmedIcon /> : <ReceivedIcon />
const Kind = () => <Text thin>{tx.type === 'sent' ? 'Sent' : 'Received'}</Text>
const Date = () => <TextSecondary>{date}</TextSecondary>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Rename local Date component to avoid shadowing the global.

This triggers Biome’s noShadowRestrictedNames. Rename to TxDate (and its usage).

-  const Date = () => <TextSecondary>{date}</TextSecondary>
+  const TxDate = () => <TextSecondary>{date}</TextSecondary>
-        <Date />
+        <TxDate />

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (2.1.2)

[error] 48-48: Do not shadow the global "Date" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🤖 Prompt for AI Agents
In src/components/TransactionsList.tsx around line 48, the local component is
named "Date" which shadows the global Date and triggers Biome's
noShadowRestrictedNames; rename the component to "TxDate" and update all usages
in this file accordingly (replace the component declaration const Date = () =>
... with const TxDate = () => ... and change any <Date/> renders to <TxDate/>),
keeping props/children the same and ensuring imports/exports (if any) reflect
the new name.

Comment on lines +161 to +171
<IonGrid>
<IonRow class='ion-align-items-end'>
<IonCol size='4'>
<Text>{amount}</Text>
</IonCol>
<IonCol size='4'>{tags}</IonCol>
<IonCol size='4'>
<Text right>{expiry}</Text>
</IonCol>
</IonRow>
</IonGrid>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use className instead of class on React components.

React/TSX expects className. Using class can cause typing/lint issues.

-            <IonRow class='ion-align-items-end'>
+            <IonRow className='ion-align-items-end'>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<IonGrid>
<IonRow class='ion-align-items-end'>
<IonCol size='4'>
<Text>{amount}</Text>
</IonCol>
<IonCol size='4'>{tags}</IonCol>
<IonCol size='4'>
<Text right>{expiry}</Text>
</IonCol>
</IonRow>
</IonGrid>
<IonGrid>
<IonRow className='ion-align-items-end'>
<IonCol size='4'>
<Text>{amount}</Text>
</IonCol>
<IonCol size='4'>{tags}</IonCol>
<IonCol size='4'>
<Text right>{expiry}</Text>
</IonCol>
</IonRow>
</IonGrid>
🤖 Prompt for AI Agents
In src/screens/Settings/Vtxos.tsx around lines 161 to 171, the IonRow uses the
HTML attribute class='ion-align-items-end' which should be the React prop
className; change class='ion-align-items-end' to className='ion-align-items-end'
(and verify there are no other JSX elements in this file using class instead of
className).

@bordalix bordalix merged commit e7fdebd into master Oct 23, 2025
5 checks passed
@bordalix bordalix deleted the show_subdust_coins branch November 26, 2025 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants