Skip to content

feat: Add basic ledger entry page#1146

Draft
mvadari wants to merge 31 commits into
stagingfrom
entry-page
Draft

feat: Add basic ledger entry page#1146
mvadari wants to merge 31 commits into
stagingfrom
entry-page

Conversation

@mvadari

@mvadari mvadari commented Mar 31, 2025

Copy link
Copy Markdown
Collaborator

High Level Overview of Change

This PR adds a new type of page for ledger entries/objects. For now it just has a default page that shows all the fields of an object, but over time we can add special ones.

It also:

  • Adds links to these pages in the Detailed tab metadata breakdown
  • Redirects to the Account page if the object is an account
  • Handles deleted objects (if connected to a Clio node)

Context of Change

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (non-breaking change that only restructures code)
  • Tests (You added tests for code that already exists, or your new feature included in this PR)
  • Documentation Updates
  • Translation Updates
  • Release

TypeScript/Hooks Update

  • Updated files to React Hooks
  • Updated files to TypeScript

Before / After

image

Test Plan

kennyzlei and others added 13 commits December 18, 2024 10:06
## High Level Overview of Change

Fix typo for website in english translation

### Context of Change

Bug introduced in #1056

### Type of Change

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] Refactor (non-breaking change that only restructures code)
- [ ] Tests (You added tests for code that already exists, or your new
feature included in this PR)
- [ ] Documentation Updates
- [ ] Translation Updates
- [ ] Release

### TypeScript/Hooks Update

- [ ] Updated files to React Hooks
- [ ] Updated files to TypeScript
@mvadari mvadari linked an issue Apr 1, 2025 that may be closed by this pull request
Comment on lines +50 to +51
await getLedgerEntry(rippledContext, id)
return 'entry'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is there any way we can cache the result of this method invocation? It feels wasteful to invoke this API only for the purpose of checking if the hash pertains to a transaction, ledger-entry (or) an NFT.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

That change should probably be made in a separate PR

Comment thread src/rippled/lib/rippled.ts Outdated
Comment on lines 96 to 98
if (resp.error === 'lgrNotFound') {
throw new Error('invalid ledger index/hash', 400)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This RPC command always fetches the last validated ledger. This error cannot possibly occur.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Better to have an extra error handler and not need it - no need to delete it IMO

@mvadari mvadari requested a review from Copilot May 21, 2026 16:43

Copilot AI commented May 21, 2026

Copy link
Copy Markdown
Contributor

@mvadari Thanks for sending me some feedback. Unfortunately, I hit an error while trying to use the custom Copilot setup steps configured for this repository. The error I am seeing is:

no `copilot-setup-steps` job found in your `copilot-setup-steps.yml` workflow file. Please ensure you have a single job named `copilot-setup-steps`. For more details, see https://gh.io/copilot/actions-setup-steps

Once you or someone with the necessary access fixes the problem, please let me know in a comment and I'll try again. Thanks!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a new “Entry” page/route for XRPL ledger_entry objects and wires it into existing navigation (search + tx meta) so users can jump from affected ledger nodes / object IDs to a dedicated object view.

Changes:

  • Introduces /entry/:id/:tab? route and new Entry container with “Simple” + “Raw” tabs, plus redirects for certain entry types (e.g., AccountRoot).
  • Updates transaction meta renderers and some transaction/NFT UI to deep-link ledger object indices (Offer/PayChannel/RippleState/etc.) to the new Entry page.
  • Updates rippled client getLedgerEntry API (signature + optional deleted-entry support) and extends header search routing to detect ledger entry hashes.

Reviewed changes

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

Show a summary per file
File Description
src/rippled/lib/rippled.ts Updates getLedgerEntry signature and adds include_deleted support for ledger_entry calls.
src/containers/Transactions/index.tsx Minor formatting-only change.
src/containers/Transactions/DetailTab/Meta/RippleState.tsx Adds Entry-page link for RippleState affected nodes; adjusts rendered currency display.
src/containers/Transactions/DetailTab/Meta/PayChannel.tsx Adds Entry-page link for PayChannel affected nodes.
src/containers/Transactions/DetailTab/Meta/Offer.tsx Adds Entry-page link placeholder via i18n component mapping for Offer affected nodes.
src/containers/Transactions/DetailTab/Meta/MPTokenIssuance.tsx Adds Entry-page link for MPTokenIssuance affected nodes.
src/containers/Transactions/DetailTab/Meta/MPToken.tsx Adds Entry-page link for MPToken affected nodes.
src/containers/Transactions/DetailTab/Meta/index.tsx Enhances default meta line with an i18n-driven Entry-page link.
src/containers/Transactions/DetailTab/Meta/DirectoryNode.tsx Enhances directory node meta lines with an i18n-driven Entry-page link.
src/containers/TokenNonMain/TokenHeader/index.tsx Avoids rendering a transaction link row when previousTxn is missing.
src/containers/shared/components/Transaction/PaymentChannelCreate/Simple.tsx Links created channel IDs to the Entry page.
src/containers/shared/components/Transaction/NFTokenCreateOffer/Simple.tsx Links offer index to the Entry page.
src/containers/shared/components/Transaction/NFTokenCancelOffer/Simple.tsx Links offer index to the Entry page.
src/containers/shared/components/Transaction/NFTokenAcceptOffer/Simple.tsx Links offer index to the Entry page.
src/containers/NFT/NFTTabs/test/Offers.test.js Updates anchor-count assertion due to new Entry links.
src/containers/NFT/NFTTabs/Offers.tsx Links offer index values to the Entry page.
src/containers/Header/Search.tsx Extends hash-type detection/routing to include Entry-page navigation.
src/containers/Entry/SimpleTab.tsx New Simple tab layout for entries (summary + index/prev pointers).
src/containers/Entry/simpleTab.scss Styling for Entry simple tab layout.
src/containers/Entry/Simple/index.tsx Selects a “Simple” renderer for entries (currently reuses transaction mapping + fallback).
src/containers/Entry/Simple/DefaultSimple.tsx Default Entry simple renderer that displays arbitrary ledger entry fields.
src/containers/Entry/index.tsx New Entry container: fetches ledger entries, handles errors, and redirects for specific types.
src/containers/Entry/entry.scss Styling for Entry page shell/summary.
src/containers/App/routes.ts Makes accounts/transactions identifiers required in paths and adds new ENTRY_ROUTE.
src/containers/App/index.tsx Registers new Entry route and adds explicit /accounts and /transactions routes.
src/containers/Accounts/AMM/AMMAccounts/index.tsx Updates call site for new getLedgerEntry signature.
public/locales/en-US/translations.json Adds/updates i18n strings to support Entry links and Entry page UI text.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

command: 'ledger_entry',
index,
ledger_index: 'validated',
include_deleted: includeDeleted,

if (resp.error_message === 'invalidParams') {
if (resp.error === 'invalidParams') {
throw new Error('invalidParams for ledger_entry', 404)
Comment on lines +153 to +154
if (resp.error) {
throw new Error(resp.error, 500)
Comment on lines 3 to 9
export const ACCOUNT_ROUTE: RouteDefinition<{
id?: string
tab?: 'assets' | 'transactions'
assetType?: 'issued' | 'nfts' | 'mpts'
}> = {
path: '/accounts/:id?/:tab?/:assetType?',
path: '/accounts/:id/:tab?/:assetType?',
}
Comment on lines +22 to +31
<SimpleRow label={t('owner')} data-test="owner">
<Account account={owner} />
</SimpleRow>
)}
<SimpleRow label={t('prev_ledger_index')} data-test="prev-ledger-index">
<RouteLink to={LEDGER_ROUTE} params={{ identifier: prevLedgerIndex }}>
{prevLedgerIndex}
</RouteLink>
</SimpleRow>
<SimpleRow label={t('prev_tx_id')} data-test="prev-tx">
Comment on lines +2 to +27
import { ErrorBoundary } from 'react-error-boundary'
import { useTranslation } from 'react-i18next'
import { transactionTypes } from '../../shared/components/Transaction'
import { DefaultSimple } from './DefaultSimple'

export const Simple: FC<{
data: any
type: string
}> = ({ data, type }) => {
// Locate the component for the left side of the simple tab that is unique per TransactionType.
const { t } = useTranslation()
const SimpleComponent = transactionTypes[type]?.Simple
if (SimpleComponent) {
return (
<ErrorBoundary
fallback={
<div className="error">
<div>{t('component_error')}</div>
<div>{t('try_detailed_raw')}</div>
</div>
}
>
<SimpleComponent data={data} />
</ErrorBoundary>
)
}
Comment on lines +44 to +88
const { isLoading, data, error, isError } = useQuery(['entry', id], () => {
if (id === '') {
return undefined
}
if (HASH256_REGEX.test(id)) {
return getLedgerEntry(rippledSocket, id, true).catch(
(ledgerEntryRequestError) => {
const status = ledgerEntryRequestError.code
trackException(
`entry ${id} --- ${JSON.stringify(
ledgerEntryRequestError.message,
)}`,
)

return Promise.reject(status)
},
)
}

return Promise.reject(BAD_REQUEST)
})
const { width } = useWindowSize()

useEffect(() => {
trackScreenLoaded()

return () => {
window.scrollTo(0, 0)
}
}, [tab, trackScreenLoaded])

useEffect(() => {
if (id != null && data?.index != null) {
if (data.node.LedgerEntryType === 'AccountRoot') {
const path = buildPath(ACCOUNT_ROUTE, { id: data.node.Account })
navigate(path)
} else if (data.node.LedgerEntryType === 'MPTokenIssuance') {
const path = buildPath(MPT_ROUTE, { id: data.node.mpt_issuance_id })
navigate(path)
} else if (data.node.LedgerEntryType === 'AMM') {
const path = buildPath(ACCOUNT_ROUTE, { id: data.node.Account })
navigate(path)
}
}
}, [id, data, navigate])
"prev_tx_id": "Previous Modifying Transaction",
"entry_not_found": "Entry not found",
"entry_empty_title": "No entry hash supplied",
"entry_empty_hint": "Enter a entry hash in the search box",
Comment on lines 23 to +28
<Trans i18nKey="transaction_balance_line_one">
It {action} a{' '}
<b>
<Currency currency={currency} />
</b>
RippleState node between
It {action} a <b>{currency}</b>
RippleState{' '}
<RouteLink to={ENTRY_ROUTE} params={{ id: node.LedgerIndex }}>
node
</RouteLink>{' '}
Comment on lines 36 to +50
const determineHashType = async (
id: string,
rippledContext: ExplorerXrplClient,
) => {
try {
await getTransaction(rippledContext, id)
return 'transactions'
} catch (e) {
return 'nft'
try {
await getLedgerEntry(rippledContext, id)
return 'entry'
} catch (e2) {
// TODO: better error message here
return 'nft'
}
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.

Feature request: Ledger object pages

7 participants