Skip to content

feat(sdk-go): view bridge transaction history#176

Merged
MicBun merged 2 commits intomainfrom
viewHistory
Feb 17, 2026
Merged

feat(sdk-go): view bridge transaction history#176
MicBun merged 2 commits intomainfrom
viewHistory

Conversation

@MicBun
Copy link
Member

@MicBun MicBun commented Feb 16, 2026

resolves: https://github.com/truflation/website/issues/3313

Summary by CodeRabbit

  • New Features

    • Added support to retrieve transaction history for a wallet on a specified bridge, including details such as transaction type, amount, addresses, hashes, status, and block information with configurable pagination options.
  • Documentation

    • Added API reference documentation and example usage for the new history retrieval functionality.

@MicBun MicBun self-assigned this Feb 16, 2026
@MicBun MicBun added the enhancement New feature or request label Feb 16, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 16, 2026

Warning

Rate limit exceeded

@MicBun has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 57 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

This PR introduces a new GetHistory method to retrieve wallet transaction history for a specific bridge. Changes include type definitions, interface methods, multi-layer implementations, enhanced pointer field handling in decoding, integration tests, documentation, and example usage.

Changes

Cohort / File(s) Summary
Type Definitions
core/types/bridge_types.go, core/types/stream.go, core/types/tsn_client.go
Added BridgeHistory and GetHistoryInput types with validation tags; added GetHistory method signatures to IAction and Client interfaces.
Core Implementation
core/contractsapi/bridge_history.go
Implemented GetHistory method with input validation, default parameter handling (limit: 20, offset: 0), action invocation, and result decoding.
Pointer Field Handling
core/contractsapi/decode_call_results.go
Enhanced prepareScanTargetsForStructInternal to handle pointer fields: allocate memory for nil pointers, use nil as target when rowSrc is nil, and pass rowSrc through the decoding pipeline.
Client Layer
core/tnclient/client.go, core/tnclient/actions_transport.go
Added GetHistory wrapper in Client that delegates to actions; added not-implemented stub in TransportAction for consistency.
Documentation & Examples
docs/api-reference.md, examples/history_example/main.go
Added API documentation for GetHistory and BridgeHistory type; created runnable example demonstrating key loading, client initialization, and tabulated result formatting.
Tests & Dependencies
tests/integration/bridge_history_test.go, go.mod
Added integration test covering bridge-not-found and input validation scenarios; updated kwil-db dependencies to latest versions.

Sequence Diagram

sequenceDiagram
    participant Client as SDK Client
    participant Action as Action Handler
    participant ContractAPI as ContractAPI Layer
    participant Decoder as DecodeCallResult
    
    Client->>Client: LoadActions()
    Client->>Action: GetHistory(ctx, input)
    Action->>Action: Validate BridgeIdentifier & Wallet
    Action->>Action: Apply defaults (limit:20, offset:0)
    Action->>Action: Build actionName & args
    Action->>ContractAPI: call(ctx, actionName, args)
    ContractAPI->>ContractAPI: Execute contract method
    ContractAPI-->>Action: Return raw result
    Action->>Decoder: DecodeCallResult(result)
    Decoder->>Decoder: Handle pointer fields & nil values
    Decoder-->>Action: []BridgeHistory
    Action-->>Client: []BridgeHistory
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • pr-time-tracker
  • outerlook

Poem

🐰 A curious rabbit hops through the chain,
Seeking transaction tales of loss and gain,
With GetHistory's charm, the past unfolds,
Bridge histories now—what stories they hold! 🌉✨

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(sdk-go): view bridge transaction history' clearly and concisely summarizes the main change—adding functionality to view bridge transaction history in the SDK.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch viewHistory

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.

@holdex
Copy link

holdex bot commented Feb 16, 2026

Time Submission Status

Member Status Time Action Last Update
MicBun ✅ Submitted 4h Update time Feb 17, 2026, 12:01 AM

You can submit time with the command. Example:

@holdex pr submit-time 15m

See available commands to help comply with our Guidelines.

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

🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@core/contractsapi/bridge_history.go`:
- Around line 19-26: Validate and bound-check user-supplied paging values before
using them: when reading input.Limit and input.Offset, ensure they are
non-nil-checked and that their values are not negative (return a bad-request
error if negative), set a sensible default for limit (keep limit := 20) and cap
limit to a maximum (e.g., maxLimit := 100) before assigning to the local
variables `limit` and `offset`; use `input.Limit`, `input.Offset`, and the local
`limit`/`offset` variables as the change points and add a constant like
`maxLimit` or reuse an existing pagination config.

In `@core/types/bridge_types.go`:
- Around line 18-23: GetHistoryInput's Limit and Offset lack validation so
negative values could slip through; update the struct tags on GetHistoryInput
(fields Limit and Offset) to include validation constraints (e.g., for Limit use
`validate:"omitempty,min=1"` to require positive limits and for Offset use
`validate:"omitempty,min=0"` to forbid negatives), and ensure the validation
library is invoked where GetHistoryInput is validated so these constraints are
enforced.

In `@core/types/stream.go`:
- Around line 127-129: GetHistory is a bridge-specific operation that breaks
IAction cohesion and forces non-bridge implementors (e.g., TransportAction) to
stub it; refactor by moving GetHistory off IAction into a new IBridgeAction
interface (or exposing it directly on Client/LoadActions as IBridgeAction) and
update implementations to implement IBridgeAction instead of adding a stub for
GetHistory; keep existing pattern in mind for
BatchStreamExists/BatchFilterStreamsByExistence so callers remain compatible and
update any factory/LoadActions wiring to return the new interface where needed.

In `@docs/api-reference.md`:
- Around line 2049-2066: The BridgeHistory struct documentation is incorrectly
located inside the "Attestation Actions Interface > Types" section; move the
entire BridgeHistory definition out of that attestation block and place it
either in a new "Bridge History Types" section or under the GetHistory method
documentation (reference symbol: BridgeHistory and GetHistory) so readers no
longer associate it with attestation; ensure you remove the original occurrence
and update any nearby cross-references or table-of-contents anchors that pointed
to the old location.

In `@examples/history_example/main.go`:
- Around line 35-37: The comment on the endpoint default is misleading: update
the comment next to the endpoint variable assignment (the line setting endpoint
= "https://gateway.testnet.truf.network") to accurately state that it defaults
to the testnet gateway (e.g., "Default to testnet gateway") or remove the "local
node" wording so it reflects the true URL.
- Around line 90-101: The helper formatHexShort is being redeclared inside the
loop and the surrounding draft comments are noise; move the formatHexShort
function definition out of the loop (declare it once above the loop that prints
history) and remove the draft/comment lines (those "Shorten hashes..." and "Or
shortening..." notes) so the loop only contains the printing logic and calls to
formatHexShort.
🧹 Nitpick comments (4)
🤖 Fix all nitpicks with AI agents
Verify each finding against the current code and only fix it if needed.


In `@core/contractsapi/bridge_history.go`:
- Around line 19-26: Validate and bound-check user-supplied paging values before
using them: when reading input.Limit and input.Offset, ensure they are
non-nil-checked and that their values are not negative (return a bad-request
error if negative), set a sensible default for limit (keep limit := 20) and cap
limit to a maximum (e.g., maxLimit := 100) before assigning to the local
variables `limit` and `offset`; use `input.Limit`, `input.Offset`, and the local
`limit`/`offset` variables as the change points and add a constant like
`maxLimit` or reuse an existing pagination config.

In `@core/types/bridge_types.go`:
- Around line 18-23: GetHistoryInput's Limit and Offset lack validation so
negative values could slip through; update the struct tags on GetHistoryInput
(fields Limit and Offset) to include validation constraints (e.g., for Limit use
`validate:"omitempty,min=1"` to require positive limits and for Offset use
`validate:"omitempty,min=0"` to forbid negatives), and ensure the validation
library is invoked where GetHistoryInput is validated so these constraints are
enforced.

In `@core/types/stream.go`:
- Around line 127-129: GetHistory is a bridge-specific operation that breaks
IAction cohesion and forces non-bridge implementors (e.g., TransportAction) to
stub it; refactor by moving GetHistory off IAction into a new IBridgeAction
interface (or exposing it directly on Client/LoadActions as IBridgeAction) and
update implementations to implement IBridgeAction instead of adding a stub for
GetHistory; keep existing pattern in mind for
BatchStreamExists/BatchFilterStreamsByExistence so callers remain compatible and
update any factory/LoadActions wiring to return the new interface where needed.

In `@examples/history_example/main.go`:
- Around line 90-101: The helper formatHexShort is being redeclared inside the
loop and the surrounding draft comments are noise; move the formatHexShort
function definition out of the loop (declare it once above the loop that prints
history) and remove the draft/comment lines (those "Shorten hashes..." and "Or
shortening..." notes) so the loop only contains the printing logic and calls to
formatHexShort.
core/types/stream.go (1)

127-129: Consider whether GetHistory belongs on IAction or a dedicated interface.

IAction currently groups stream-related operations (records, indexes, visibility, permissions). GetHistory is a bridge-specific operation that doesn't conceptually relate to stream data. A separate IBridgeAction interface (or placing it on the Client directly without going through LoadActions()) would preserve interface cohesion and avoid forcing all IAction implementors (including TransportAction) to stub this method.

That said, this follows the same pattern as BatchStreamExists/BatchFilterStreamsByExistence which are also not strictly per-stream operations, so this may be an intentional architectural choice.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/types/stream.go` around lines 127 - 129, GetHistory is a bridge-specific
operation that breaks IAction cohesion and forces non-bridge implementors (e.g.,
TransportAction) to stub it; refactor by moving GetHistory off IAction into a
new IBridgeAction interface (or exposing it directly on Client/LoadActions as
IBridgeAction) and update implementations to implement IBridgeAction instead of
adding a stub for GetHistory; keep existing pattern in mind for
BatchStreamExists/BatchFilterStreamsByExistence so callers remain compatible and
update any factory/LoadActions wiring to return the new interface where needed.
core/types/bridge_types.go (1)

18-23: Consider adding validation constraints on Limit and Offset.

Negative values for Limit or Offset could produce unexpected query behavior. You could add validate:"omitempty,min=0" (or min=1 for Limit) to catch invalid input early on the client side, consistent with how validation is already used on the required fields.

♻️ Optional: Add validation constraints
 type GetHistoryInput struct {
 	BridgeIdentifier string `validate:"required"`
 	Wallet           string `validate:"required"`
-	Limit            *int
-	Offset           *int
+	Limit            *int   `validate:"omitempty,min=1"`
+	Offset           *int   `validate:"omitempty,min=0"`
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/types/bridge_types.go` around lines 18 - 23, GetHistoryInput's Limit and
Offset lack validation so negative values could slip through; update the struct
tags on GetHistoryInput (fields Limit and Offset) to include validation
constraints (e.g., for Limit use `validate:"omitempty,min=1"` to require
positive limits and for Offset use `validate:"omitempty,min=0"` to forbid
negatives), and ensure the validation library is invoked where GetHistoryInput
is validated so these constraints are enforced.
core/contractsapi/bridge_history.go (1)

19-26: No validation on Limit and Offset values.

User-supplied *input.Limit and *input.Offset are used directly without bounds checking. A negative limit or offset would be passed straight to the backend, which may produce unexpected results or errors that are harder to diagnose.

Proposed fix
 	limit := 20
 	if input.Limit != nil {
+		if *input.Limit < 0 {
+			return nil, errors.New("limit must be non-negative")
+		}
 		limit = *input.Limit
 	}
 	offset := 0
 	if input.Offset != nil {
+		if *input.Offset < 0 {
+			return nil, errors.New("offset must be non-negative")
+		}
 		offset = *input.Offset
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/contractsapi/bridge_history.go` around lines 19 - 26, Validate and
bound-check user-supplied paging values before using them: when reading
input.Limit and input.Offset, ensure they are non-nil-checked and that their
values are not negative (return a bad-request error if negative), set a sensible
default for limit (keep limit := 20) and cap limit to a maximum (e.g., maxLimit
:= 100) before assigning to the local variables `limit` and `offset`; use
`input.Limit`, `input.Offset`, and the local `limit`/`offset` variables as the
change points and add a constant like `maxLimit` or reuse an existing pagination
config.
examples/history_example/main.go (1)

90-101: Move formatHexShort out of the loop and remove draft comments.

The helper is re-declared on every iteration, and lines 90-92 read like leftover notes rather than documentation.

Proposed cleanup

Define formatHexShort once before the loop and drop the draft comments:

+	formatHexShort := func(b []byte) string {
+		if len(b) == 0 {
+			return "null"
+		}
+		if len(b) > 4 {
+			return fmt.Sprintf("0x%x...", b[:4])
+		}
+		return fmt.Sprintf("0x%x", b)
+	}
+
 	for _, rec := range history {
 		// Format timestamp
 		tm := time.Unix(rec.BlockTimestamp, 0)
 		timeStr := tm.Format(time.RFC3339)
 
-		// Shorten hashes for display if needed, but printing full for now as per request
-		// Or shortening to keep table readable? The CLI output truncated them.
-		// "0x%x..." logic was used before. I will use a helper to optionally shorten.
-		formatHexShort := func(b []byte) string {
-			if len(b) == 0 {
-				return "null"
-			}
-			if len(b) > 4 {
-				return fmt.Sprintf("0x%x...", b[:4])
-			}
-			return fmt.Sprintf("0x%x", b)
-		}
-
 		// Handle nullable external block height
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/history_example/main.go` around lines 90 - 101, The helper
formatHexShort is being redeclared inside the loop and the surrounding draft
comments are noise; move the formatHexShort function definition out of the loop
(declare it once above the loop that prints history) and remove the
draft/comment lines (those "Shorten hashes..." and "Or shortening..." notes) so
the loop only contains the printing logic and calls to formatHexShort.

@MicBun MicBun merged commit 63fb005 into main Feb 17, 2026
4 checks passed
@MicBun MicBun deleted the viewHistory branch February 17, 2026 00:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant