Skip to content

feat: bridge withdrawal#178

Merged
MicBun merged 3 commits intomainfrom
withdrawal
Feb 20, 2026
Merged

feat: bridge withdrawal#178
MicBun merged 3 commits intomainfrom
withdrawal

Conversation

@MicBun
Copy link
Member

@MicBun MicBun commented Feb 20, 2026

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

Summary by CodeRabbit

  • New Features

    • Retrieve bridge wallet balances
    • Execute token withdrawals with transaction-hash return
    • Obtain withdrawal proofs for claiming on EVM chains
  • Documentation

    • Added Bridge Actions API reference with method signatures and usage examples
  • Tests

    • Added integration tests for balance queries, withdrawals, proof retrieval, and input validation

@MicBun MicBun self-assigned this Feb 20, 2026
@MicBun MicBun added the enhancement New feature or request label Feb 20, 2026
@holdex
Copy link

holdex bot commented Feb 20, 2026

Time Submission Status

Member Status Time Action Last Update
MicBun ✅ Submitted 4h Update time Feb 20, 2026, 4:14 PM

You can submit time with the command. Example:

@holdex pr submit-time 15m

See available commands to help comply with our Guidelines.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 20, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds bridge-related client, transport, action, and type support for wallet balance, token withdrawal, and withdrawal-proof retrieval; implements Action methods and integration tests; updates interfaces and docs.

Changes

Cohort / File(s) Summary
Types & Interfaces
core/types/bridge_types.go, core/types/stream.go, core/types/tsn_client.go
Added WithdrawalProof and GetWithdrawalProofInput types, changed BridgeHistory.BlockHeight to uint64, and added GetWalletBalance, Withdraw, and GetWithdrawalProof method signatures to interfaces.
Action Implementations
core/contractsapi/bridge_actions.go, core/contractsapi/withdrawal_proof.go
Added Action.GetWalletBalance, Action.Withdraw, and Action.GetWithdrawalProof with input validation, dynamic action name construction, internal call/execute invocations, result handling/decoding, and error propagation.
Transport & Client
core/tnclient/actions_transport.go, core/tnclient/client.go
Added TransportAction stub methods (not-implemented) and Client methods that load Actions and delegate to the new Action methods.
Docs & Tests
docs/api-reference.md, tests/integration/bridge_actions_test.go
Added API documentation for bridge actions (duplicated block present) and integration tests exercising balance, withdraw, withdrawal-proof, and input validation scenarios.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Actions as Action
    participant Transport
    participant Service as TN_Service

    Client->>Actions: GetWalletBalance(ctx, bridge, wallet)
    Actions->>Actions: validate inputs, build actionName
    Actions->>Transport: call(actionName, [wallet])
    Transport->>Service: forward call
    Service-->>Transport: result
    Transport-->>Actions: result or error
    Actions-->>Client: balance or error

    Client->>Actions: Withdraw(ctx, bridge, amount, recipient)
    Actions->>Actions: validate inputs, parse amount, build actionName
    Actions->>Transport: execute(actionName, [[recipient, amount]])
    Transport->>Service: forward execute
    Service-->>Transport: txHash
    Transport-->>Actions: txHash or error
    Actions-->>Client: txHash or error

    Client->>Actions: GetWithdrawalProof(ctx, input)
    Actions->>Actions: validate inputs, build actionName
    Actions->>Transport: call(actionName, [wallet])
    Transport->>Service: forward call
    Service-->>Transport: proofs payload
    Transport-->>Actions: payload or error
    Actions-->>Client: []WithdrawalProof or error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • feat: bridge withdrawal #178 — Adds the same bridge-related methods and types (GetWalletBalance, Withdraw, GetWithdrawalProof, WithdrawalProof, GetWithdrawalProofInput).

Suggested reviewers

  • pr-time-tracker
  • outerlook

Poem

🐰 I hopped across the code today,
Built bridges where the tokens play,
Balances checked, withdrawals sent,
Proofs fetched neat, tests run and bent,
I twitched my nose — commits away!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 'feat: bridge withdrawal' accurately reflects the main change—adding bridge withdrawal functionality with GetWalletBalance, Withdraw, and GetWithdrawalProof methods across the codebase.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch withdrawal

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.

@MicBun MicBun changed the title feat: wihtdraw token feat: withdraw token Feb 20, 2026
@MicBun MicBun changed the title feat: withdraw token feat: bridge withdrawal Feb 20, 2026
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: 4

🧹 Nitpick comments (1)
tests/integration/bridge_actions_test.go (1)

53-66: Withdraw subtest can never fail — both error and success branches are unconditionally accepted.

The current logic:

if err != nil {
    t.Logf(...)      // always passes
} else {
    assert.NotEmpty(...) // only fails if hash is empty AND err is nil
}

A nil error with an empty hash is the only failure, which is an unlikely edge case. The test provides no meaningful regression coverage. Since the test expectation is for a non-existent bridge to behave consistently with the other subtests (node-level error or mempool acceptance), at least assert one specific outcome.

♻️ Suggested improvement
-	hash, err := tnClient.Withdraw(bridgeID, amount, recipient)
-
-	if err != nil {
-		t.Logf("Withdraw returned error (acceptable): %v", err)
-	} else {
-		assert.NotEmpty(t, hash, "should return a transaction hash if no error")
-		t.Logf("Withdraw returned hash (acceptable): %v", hash)
-	}
+	hash, err := tnClient.Withdraw(bridgeID, amount, recipient)
+
+	// Either a node error OR a valid mempool tx hash is acceptable, but not both absent.
+	if err != nil {
+		t.Logf("Withdraw returned error (acceptable): %v", err)
+	} else {
+		require.NotEmpty(t, hash, "must return a non-empty transaction hash when no error")
+		t.Logf("Withdraw returned hash (acceptable): %v", hash)
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integration/bridge_actions_test.go` around lines 53 - 66, The Withdraw
subtest currently accepts both error and success paths unconditionally; update
the assertions in the tnClient.Withdraw(bridgeID, amount, recipient) block so
the test fails unless one clear outcome holds — either assert that err is
non-nil (expecting a node-level error for the non_existent_bridge) or assert
that err is nil and hash is non-empty (mempool acceptance). Locate the Withdraw
subtest variables bridgeID/amount/recipient and the call tnClient.Withdraw and
replace the current if/else logging with a single assertion that enforces (err
!= nil) || (err == nil && hash != ""), e.g., require one of those conditions to
be true so the test provides meaningful coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@core/contractsapi/bridge_actions.go`:
- Around line 28-32: GetWalletBalance currently checks only the outer slice
(res.Values) but then reads res.Values[0][0] which can panic if the inner slice
is empty, and fmt.Sprint on a nil cell yields "<nil>" instead of "0". Update the
return path in GetWalletBalance to: verify len(res.Values[0]) > 0 before
accessing [0][0], and treat a nil cell (res.Values[0][0] == nil) as zero by
returning "0", nil; otherwise return the formatted cell value. Ensure you
reference res.Values in your checks and keep the same function signature for
GetWalletBalance.

In `@core/tnclient/client.go`:
- Around line 302-318: Update the public API to accept context.Context for
wallet and withdrawal operations: add ctx context.Context to the signatures of
GetWalletBalance and Withdraw in the IAction interface (core/types/stream.go)
and the Client interface (core/types/tsn_client.go), then update all
implementations and callers to pass the context (including
Client.GetWalletBalance and Client.Withdraw in core/tnclient/client.go, the
bridge actions implementation in core/contractsapi/bridge_actions.go, the
transport stub in core/tnclient/actions_transport.go, and related integration
tests in tests/integration/bridge_actions_test.go); ensure each file imports the
context package and that calls to underlying actions use the passed ctx instead
of context.Background(), and run/update tests to reflect the new signatures.

In `@core/types/bridge_types.go`:
- Around line 26-37: The WithdrawalProof struct is missing the BlockHeight field
described in the API; add a new field named BlockHeight (e.g., type uint64) with
the json tag "block_height" to the WithdrawalProof struct (near the existing
CreatedAt field) so callers can correlate withdrawals with on-chain state, and
ensure any (de)serialization and usages of WithdrawalProof handle the new field
(update any marshalling, constructors, or tests referencing WithdrawalProof as
needed).

In `@core/types/stream.go`:
- Around line 131-138: The GetWalletBalance and Withdraw method signatures in
the IAction interface lack the ctx context.Context parameter—add ctx as the
first parameter to GetWalletBalance( ctx context.Context, bridgeIdentifier
string, walletAddress string) (string, error) and Withdraw(ctx context.Context,
bridgeIdentifier string, amount string, recipient string) (string, error); then
propagate this change to the parallel Client interface in
core/types/tsn_client.go and update all implementations and callers (notably the
methods in core/contractsapi/bridge_actions.go, core/tnclient/client.go,
core/tnclient/actions_transport.go) to accept the ctx argument and stop using
context.Background() (pass the incoming ctx through), and update integration
tests to provide an appropriate context when calling these methods.

---

Duplicate comments:
In `@core/types/tsn_client.go`:
- Around line 52-57: The interface in core/types/tsn_client.go is missing
context.Context on two methods (GetWalletBalance and Withdraw) similar to
core/types/stream.go; update the signatures of GetWalletBalance(bridgeIdentifier
string, walletAddress string) (string, error) and Withdraw(bridgeIdentifier
string, amount string, recipient string) (string, error) to accept ctx
context.Context as the first parameter (i.e., GetWalletBalance(ctx
context.Context, ...) and Withdraw(ctx context.Context, ...)), keep
GetWithdrawalProof as-is, and then update all implementations and call sites of
these methods to pass the context through (adjust any functions referencing
GetWalletBalance or Withdraw to supply ctx).

---

Nitpick comments:
In `@tests/integration/bridge_actions_test.go`:
- Around line 53-66: The Withdraw subtest currently accepts both error and
success paths unconditionally; update the assertions in the
tnClient.Withdraw(bridgeID, amount, recipient) block so the test fails unless
one clear outcome holds — either assert that err is non-nil (expecting a
node-level error for the non_existent_bridge) or assert that err is nil and hash
is non-empty (mempool acceptance). Locate the Withdraw subtest variables
bridgeID/amount/recipient and the call tnClient.Withdraw and replace the current
if/else logging with a single assertion that enforces (err != nil) || (err ==
nil && hash != ""), e.g., require one of those conditions to be true so the test
provides meaningful coverage.

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.

🧹 Nitpick comments (1)
core/types/bridge_types.go (1)

25-38: BlockHeight type is inconsistent with BridgeHistory.BlockHeight.

BridgeHistory.BlockHeight (line 12) is int64, while WithdrawalProof.BlockHeight (line 31) is uint64. Both represent Kwil block heights. The inconsistency requires explicit type conversions whenever code handles both structs and creates a confusing public API contract.

uint64 is the more semantically correct choice for a monotonically increasing block number. Consider aligning BridgeHistory.BlockHeight to uint64 as well for consistency across the bridge-related types.

🤖 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 25 - 38, BridgeHistory.BlockHeight
is int64 while WithdrawalProof.BlockHeight is uint64 causing awkward
conversions; change the BridgeHistory struct's BlockHeight field type from int64
to uint64 (i.e., update BridgeHistory.BlockHeight to uint64) so both
bridge-related types use the same unsigned width, and then update any call sites
that assumed int64 to use uint64 or perform explicit casts where necessary
(search for BridgeHistory, WithdrawalProof usages to adjust conversions).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@core/types/bridge_types.go`:
- Around line 25-38: BridgeHistory.BlockHeight is int64 while
WithdrawalProof.BlockHeight is uint64 causing awkward conversions; change the
BridgeHistory struct's BlockHeight field type from int64 to uint64 (i.e., update
BridgeHistory.BlockHeight to uint64) so both bridge-related types use the same
unsigned width, and then update any call sites that assumed int64 to use uint64
or perform explicit casts where necessary (search for BridgeHistory,
WithdrawalProof usages to adjust conversions).

@MicBun MicBun merged commit 2f87974 into main Feb 20, 2026
3 of 4 checks passed
@MicBun MicBun deleted the withdrawal branch February 20, 2026 16:14
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