feat: read a transaction's decoded input#164
Conversation
Time Submission Status
Submit or update total time with: Add time on top of previous submission with: See available commands to help comply with our Guidelines. |
|
Warning Review limit reached
Next review available in: 46 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis PR bumps the kwil-js dependency, adds a new ChangesTransaction Payload Decoding
UUID Formatting and Array NULL Fidelity
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant TransactionAction
participant KwilClient
participant TransactionPayload
Caller->>TransactionAction: getTransactionInput(txId)
TransactionAction->>KwilClient: txInfo(hash)
KwilClient-->>TransactionAction: tx response with payload
TransactionAction->>TransactionAction: base64ToBytes(payload)
TransactionAction->>TransactionPayload: decodeTransactionPayload(bytes)
TransactionPayload-->>TransactionAction: DecodedTransactionPayload
TransactionAction-->>Caller: DecodedTransactionPayload
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
|
@holdex pr submit-time 4h30m |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
src/contracts-api/transactionAction.ts (2)
3-3: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse
import typefor the type-only import.
DecodedTransactionPayloadis only used as a type but is imported alongside the value import. Splitting it out avoids relying on the bundler/tsc to elide the type-only binding under stricterisolatedModules/verbatimModuleSyntaxconfigs.♻️ Proposed fix
-import { decodeTransactionPayload, DecodedTransactionPayload } from "../util/TransactionPayload"; +import { decodeTransactionPayload } from "../util/TransactionPayload"; +import type { DecodedTransactionPayload } from "../util/TransactionPayload";🤖 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 `@src/contracts-api/transactionAction.ts` at line 3, The import in transactionAction should separate the type-only symbol from the runtime value import. Update the existing import so decodeTransactionPayload remains a normal import, while DecodedTransactionPayload is brought in with import type to keep the module compatible with stricter isolatedModules/verbatimModuleSyntax settings.
253-258: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd tx context when payload decoding fails.
If
decodeTransactionPayloadthrows (truncated/unsupported-version payload), the raised error won't reference which transaction failed, making production troubleshooting harder — especially since this method is designed to be called generically across arbitrary tx hashes.♻️ Proposed fix
- return decodeTransactionPayload(payloadBytes); + try { + return decodeTransactionPayload(payloadBytes); + } catch (error) { + throw new Error( + `Failed to decode transaction input for ${input.txId}: ${(error as Error).message}` + ); + }🤖 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 `@src/contracts-api/transactionAction.ts` around lines 253 - 258, The payload decoding path in transactionAction.ts does not add any transaction-specific context when decodeTransactionPayload fails, so update the decode flow to catch and rethrow with identifying tx details from the current body/receipt object. Keep the existing payloadBytes conversion logic, but wrap the decodeTransactionPayload(payloadBytes) call in a try/catch and include the transaction hash or other available transaction identifier in the thrown error message so failures can be traced to the exact tx.src/util/AttestationEncoding.ts (1)
391-399: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueOptional: extract shared null-flag decode helper.
The
item.length === 0 || item[0] === 0null check is duplicated between the array branch and the scalar branch (withdecodeSingleValue(typeName, x.slice(1))following in both). A small shared helper (e.g.decodeFlaggedValue(typeName, bytes)) would remove the duplication and make future changes to the null-flag convention safer to keep in sync.♻️ Possible refactor
+function decodeFlaggedValue(typeName: string, item: Uint8Array): any { + return item.length === 0 || item[0] === 0 ? null : decodeSingleValue(typeName, item.slice(1)); +} + export function decodedValueToJS(decoded: DecodedEncodedValue): any { const typeName = decoded.type.name.toLowerCase(); if (decoded.type.is_array) { - return decoded.data.map((item) => - item.length === 0 || item[0] === 0 ? null : decodeSingleValue(typeName, item.slice(1)) - ); + return decoded.data.map((item) => decodeFlaggedValue(typeName, item)); } if (decoded.data.length === 0) { return null; } - const firstItem = decoded.data[0]; - if (firstItem.length === 0 || firstItem[0] === 0) { - return null; - } - - return decodeSingleValue(typeName, firstItem.slice(1)); + return decodeFlaggedValue(typeName, decoded.data[0]); }Also applies to: 401-408
🤖 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 `@src/util/AttestationEncoding.ts` around lines 391 - 399, The null-flag decoding logic is duplicated in the array handling path and the scalar branch in AttestationEncoding’s decode flow. Extract the repeated “flagged value” logic into a shared helper (for example, a helper used by decodeSingleValue and the array branch) that checks the null marker and then decodes the payload, so both branches use the same implementation and stay in sync.
🤖 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.
Nitpick comments:
In `@src/contracts-api/transactionAction.ts`:
- Line 3: The import in transactionAction should separate the type-only symbol
from the runtime value import. Update the existing import so
decodeTransactionPayload remains a normal import, while
DecodedTransactionPayload is brought in with import type to keep the module
compatible with stricter isolatedModules/verbatimModuleSyntax settings.
- Around line 253-258: The payload decoding path in transactionAction.ts does
not add any transaction-specific context when decodeTransactionPayload fails, so
update the decode flow to catch and rethrow with identifying tx details from the
current body/receipt object. Keep the existing payloadBytes conversion logic,
but wrap the decodeTransactionPayload(payloadBytes) call in a try/catch and
include the transaction hash or other available transaction identifier in the
thrown error message so failures can be traced to the exact tx.
In `@src/util/AttestationEncoding.ts`:
- Around line 391-399: The null-flag decoding logic is duplicated in the array
handling path and the scalar branch in AttestationEncoding’s decode flow.
Extract the repeated “flagged value” logic into a shared helper (for example, a
helper used by decodeSingleValue and the array branch) that checks the null
marker and then decodes the payload, so both branches use the same
implementation and stay in sync.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9259095a-d3c5-4e9d-a90d-80ac64ef42fc
📒 Files selected for processing (5)
package.jsonsrc/contracts-api/transactionAction.tssrc/internal.tssrc/util/AttestationEncoding.tssrc/util/TransactionPayload.ts
resolves: https://github.com/trufnetwork/trufscan/issues/168
What this does
Adds a way to read what an
executetransaction actually did — the action itcalled and its arguments (the deployed stream IDs from a deploy, the records
from an insert) — from a transaction hash or a raw payload. Previously only
attestations exposed their decoded contents; a deploy or insert surfaced only
an opaque length-prefixed payload from
txInfo.@trufnetwork/kwil-jsto 0.9.13 and decodes the payload with itscanonical
Utils.decodeActionExecution/Utils.decodeValue, so the wirelayout has a single source of truth.
decodeTransactionPayload(payload)→{ namespace, action, arguments },each argument decoded to a native value (text→string, integer→bigint, bool,
bytea→Uint8Array, uuid→string, numeric→string, null). Exported publicly.
TransactionAction.getTransactionInput({ txId })— fetches viatxInfoand decodes; complements
getTransactionEvent(which reads fee-ledger data).Usage
Also fixes (value-decode correctness)
An adversarial review of the shared value decoder (
AttestationEncoding, used byattestation and orderbook decoding) surfaced three confirmed bugs, now fixed with
regression tests:
formatted as a canonical
8-4-4-4-12string.null.nullinstead of[].Tests
TransactionPayload.tsinline tests decode a realActionExecution.MarshalBinarypayload from kwil-db byte-for-byte, including anegative int64.
AttestationEncoding.tsgains 6 regression tests round-tripping through thekwil-js encoder (uuid, leading/trailing-null arrays, empty array, scalar null).
Full unit suite (276 tests) green against kwil-js 0.9.13; typecheck and build
(ESM/CJS/types) pass.
Related
Summary by CodeRabbit
New Features
Bug Fixes