fix(scan): prefix indexer-rs txids with 0x before passing to viem#78
Conversation
indexer-rs stores txids bare ("0b3187..."). normalizeTx + the list
mapper copied them as-is into TransactionData.id, so downstream
consumers — TokenTransfers + TxLogs — passed the bare form into
viem's getTransactionReceipt({ hash }), which expects `0x${string}`
and throws otherwise. The throw escaped to the global error
boundary → user saw 'Terjadi kesalahan' instead of the tx detail.
Prefix once at the normalizer boundary so every caller of
TransactionData.id gets the EVM-canonical form.
📝 WalkthroughWalkthroughThis PR normalizes transaction IDs returned by the backend to consistently use the EVM-canonical Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/scan/lib/api.ts`:
- Around line 391-392: Extract a shared helper function normalizeTxid(txid:
string) that ensures a single lowercase "0x" prefix: if txid is falsy return it,
if it matches /^0x/i return txid.replace(/^0x/i, "0x"), else return "0x" + txid.
Replace the inline logic that builds id (the `const id = txid &&
!txid.startsWith("0x") ? \`0x\${txid}\` : txid;` expression and the similar
occurrence later) to call normalizeTxid(txid) so both mappings use the same
case-insensitive normalizer.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 8ab2b763-eb36-4adb-8ee6-2525628ed5ad
📒 Files selected for processing (1)
apps/scan/lib/api.ts
| const id = txid && !txid.startsWith("0x") ? `0x${txid}` : txid; | ||
| return { |
There was a problem hiding this comment.
Use one case-insensitive txid normalizer for both mappings.
At Line 391 and Line 438, startsWith("0x") is case-sensitive, so 0X... gets double-prefixed (0x0X...). Extract a shared helper and use /^0x/i to avoid malformed IDs and future drift.
Proposed patch
+function normalizeEvmTxId(txid?: string): string {
+ const v = (txid ?? "").trim();
+ if (!v) return "";
+ return /^0x/i.test(v) ? `0x${v.slice(2)}` : `0x${v}`;
+}
+
function normalizeTx(raw: RawTxDetail): TransactionData | null {
const tx = raw.transaction;
if (!tx) return null;
@@
- const txid = tx.txid ?? "";
- const id = txid && !txid.startsWith("0x") ? `0x${txid}` : txid;
+ const id = normalizeEvmTxId(tx.txid);
return {
id,
@@
const rows = Array.isArray(res) ? res : (res.transactions ?? []);
return rows.map((t): TransactionData => ({
- id: t.txid && !t.txid.startsWith("0x") ? `0x${t.txid}` : t.txid,
+ id: normalizeEvmTxId(t.txid),
from: t.from,Also applies to: 438-438
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/scan/lib/api.ts` around lines 391 - 392, Extract a shared helper
function normalizeTxid(txid: string) that ensures a single lowercase "0x"
prefix: if txid is falsy return it, if it matches /^0x/i return
txid.replace(/^0x/i, "0x"), else return "0x" + txid. Replace the inline logic
that builds id (the `const id = txid && !txid.startsWith("0x") ? \`0x\${txid}\`
: txid;` expression and the similar occurrence later) to call
normalizeTxid(txid) so both mappings use the same case-insensitive normalizer.
Why
Operator clicked a tx detail page and got the global error boundary ("Terjadi kesalahan") instead of the tx data. The indexer-rs API returned the tx correctly; the failure was client-side.
Cause: indexer-rs stores txids bare (
"0b3187c4e9e4...").normalizeTxinlib/api.tscopied that as-is intoTransactionData.id. Downstream consumersTokenTransfers+TxLogsthen passedtx.idstraight into viem'sgetTransactionReceipt({ hash })— viem'sHashtype is\0x${string}`` and the bare form throws at runtime. Uncaught throw → error boundary.What
Prefix
0xonce at the normalizer boundary so every caller downstream gets EVM-canonical form. Two sites:normalizeTx(single-tx detail)fetchLatestTransactions(list mapper)Both check
startsWith("0x")before prepending, so a future indexer that already serves prefixed txids stays a no-op.Verify
Hard-reload
https://scan.sentrixchain.com/tx/0x0b3187c4e9e4b36da940f1447b75b2bd89102ccbc36e2fd654942b2e84c94375after deploy — should render the WSRX deposit details with the Tokens Transferred panel populated, no error boundary.Summary by CodeRabbit
0xprefix for uniform display across the app.