Skip to content

Refactor calibnet wallet test#6983

Open
sudo-shashank wants to merge 20 commits into
mainfrom
shashank/refactor-wallet-test
Open

Refactor calibnet wallet test#6983
sudo-shashank wants to merge 20 commits into
mainfrom
shashank/refactor-wallet-test

Conversation

@sudo-shashank
Copy link
Copy Markdown
Contributor

@sudo-shashank sudo-shashank commented Apr 30, 2026

Summary of changes

Changes introduced in this pull request:

  • Refactor calibnet basic and delegated wallet bash scripts check to rust integration test.

Reference issue to close (if applicable)

Closes #6850

Other information and links

Change checklist

  • I have performed a self-review of my own code,
  • I have made corresponding changes to the documentation. All new code adheres to the team's documentation standards,
  • I have added tests that prove my fix is effective or that my feature works (if possible),
  • I have made sure the CHANGELOG is up-to-date. All user-facing changes should be reflected in this document.

Outside contributions

  • I have read and agree to the CONTRIBUTING document.
  • I have read and agree to the AI Policy document. I understand that failure to comply with the guidelines will lead to rejection of the pull request.

Summary by CodeRabbit

  • Tests

    • Replaced bash wallet checks with a Rust integration test suite covering export/import, funding, transfers, delegated-wallet flows, address mapping, on-chain polling, and shared test helpers plus preloaded-wallet setup.
  • Chores

    • Consolidated CI wallet verification into a single workflow job and added a dedicated test task to run the integration suite; removed the previous delegated-wallet bash runner.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • ✅ Review completed - (🔄 Check again to review again)

Walkthrough

Bash calibnet wallet integration checks were replaced by a Rust test suite. New helpers and tests under tests/ implement wallet export/import, sends (including delegated and ETH-mapped), message polling, and deletes. CI and mise task were updated to run the Rust tests; legacy delegated-wallet script removed; harness exports preloaded address.

Changes

Wallet Integration Test Migration

Layer / File(s) Summary
Helper Infrastructure
tests/common/calibnet_wallet_helpers.rs
New Rust test helpers: Backend enum, serialized local keystore lock, wallet/run_wallet_raw, export_to_temp_file, balance, send_from with retry for mempool min-gas rejection, async poll utilities, poll_until_funded/poll_until_changed, cached RPC auth from FULLNODE_API_INFO, rpc_call/rpc_call_opt, cid_from_lotus_json_result, poll_until_state_search_msg, and filecoin_to_eth. Adds constants and FOREST_TEST_PRELOADED_ADDRESS lazy value and funded_delegated_addr.
Integration Tests
tests/calibnet_wallet.rs
New ignored integration test suite exercising export/import roundtrip (local/remote), MarketAddBalance + chain polling, send to Filecoin address, send to ETH-equivalent address, wallet delete check, delegated send (local + remote). Uses helpers and parameterizes local vs remote backends.
Harness Setup
scripts/tests/harness.sh
forest_wallet_init now captures forest-wallet import preloaded_wallet.key output into FOREST_TEST_PRELOADED_ADDRESS and exports it for downstream tests.
Script Delegation / Cleanup
scripts/tests/calibnet_wallet_check.sh, scripts/tests/calibnet_delegated_wallet_check.sh
calibnet_wallet_check.sh reduced to harness init and delegates to Rust tests; calibnet_delegated_wallet_check.sh deleted.
Task Definition & Workflow
mise.toml, .github/workflows/forest.yml
Added tasks."test:wallet" to mise.toml to initialize harness and run cargo test --ignored --nocapture for calibnet_wallet. CI calibnet-wallet-check job updated to set up SCCache, install Go/mise, and invoke mise run test:wallet; removed calibnet-delegated-wallet-check job and its dependency from integration umbrella.

Sequence Diagram

sequenceDiagram
    participant CI as CI (GitHub Actions)
    participant Harness as Harness (harness.sh)
    participant Test as Rust Test Runner
    participant Helpers as Helpers (calibnet_wallet_helpers.rs)
    participant Wallet as forest-wallet CLI
    participant RPC as Forest RPC Node

    CI->>Harness: forest_wallet_init(preloaded_key)
    Harness->>Wallet: import preloaded_wallet.key
    Wallet-->>Harness: PRELOADED_ADDRESS
    Harness-->>CI: export PRELOADED_ADDRESS

    CI->>Test: cargo test --ignored (calibnet_wallet)

    Test->>Helpers: export_to_temp_file(address, Backend)
    Helpers->>Wallet: forest-wallet export <address>
    Wallet-->>Helpers: wallet.json

    Test->>Helpers: send_from(preloaded, target, amount, Backend)
    Helpers->>Wallet: forest-wallet send --from ... --to ...
    Wallet->>RPC: broadcast message
    RPC-->>Wallet: message CID
    Wallet-->>Helpers: CID

    loop poll for funding / change
      Helpers->>Wallet: forest-wallet balance <address>
      Wallet->>RPC: StateGetActor / StateReadState
      RPC-->>Wallet: balance
      Wallet-->>Helpers: balance response
    end

    Helpers->>RPC: Filecoin.StateSearchMsg (poll)
    RPC-->>Helpers: message mined
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • hanabi1224
  • LesnyRumcajs
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Refactor calibnet wallet test' accurately reflects the main change of converting bash wallet test scripts to Rust integration tests with improved maintainability.
Linked Issues check ✅ Passed The PR successfully converts bash wallet scripts to Rust integration tests (#6850), preserves feature parity (delegated wallet creation, funding, balance polling, remote operations, retry logic), uses typed APIs and structured error handling, and places tests appropriately.
Out of Scope Changes check ✅ Passed All changes are directly related to the refactoring objective: removing old bash scripts, creating new Rust tests, updating workflows, adding helpers, and updating mise configuration for the new test structure.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch shashank/refactor-wallet-test
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch shashank/refactor-wallet-test

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
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: 1

🧹 Nitpick comments (1)
tests/common/calibnet_wallet_helpers.rs (1)

127-130: ⚡ Quick win

Check first, then sleep in polling loops.

Both loops sleep before the first attempt, which adds guaranteed delay to every successful call path. Run check immediately, then sleep only between retries.

Suggested refactor
 pub async fn poll<F>(what: &str, mut check: F) -> anyhow::Result<String>
 where
     F: FnMut() -> anyhow::Result<Option<String>>,
 {
     for i in 1..=POLL_RETRIES {
         eprintln!("Polling {what} {i}/{POLL_RETRIES}");
-        tokio::time::sleep(POLL_DELAY).await;
         if let Some(value) = check()? {
             return Ok(value);
         }
+        if i < POLL_RETRIES {
+            tokio::time::sleep(POLL_DELAY).await;
+        }
     }
     bail!("Timed out waiting for {what} after {POLL_RETRIES} retries")
 }

 pub async fn poll_until_state_search_msg(msg_cid: &str) -> anyhow::Result<()> {
     for i in 1..=SEARCH_MSG_RETRIES {
-        tokio::time::sleep(SEARCH_MSG_DELAY).await;
         eprintln!("StateSearchMsg polling {msg_cid} attempt {i}/{SEARCH_MSG_RETRIES}");
         let params = json!([[], { "/": msg_cid }, 800_i64, true]);
         if rpc_call_opt("Filecoin.StateSearchMsg", params)
             .await?
             .is_some()
         {
             return Ok(());
         }
+        if i < SEARCH_MSG_RETRIES {
+            tokio::time::sleep(SEARCH_MSG_DELAY).await;
+        }
     }

Also applies to: 262-264

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

In `@tests/common/calibnet_wallet_helpers.rs` around lines 127 - 130, The polling
loops currently sleep before the first check (using POLL_DELAY in the for i in
1..=POLL_RETRIES loop), which adds unnecessary delay; update the loop(s) in
tests/common/calibnet_wallet_helpers.rs (the loop around the check() call and
the similar occurrence at the region noted around lines 262-264) to call check()
immediately and return on success, and move tokio::time::sleep(POLL_DELAY).await
to run only between retries (e.g., after a failed check and not on the final
iteration) so the first attempt is immediate and subsequent attempts are
delayed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/calibnet_wallet.rs`:
- Line 52: The tests are always invoking send_from with the remote flag
hardcoded true, so the local-wallet code path is never exercised; update the
test invocations of send_from (e.g., calls currently like
send_from(PRELOADED_ADDRESS, &target, FIL_AMT, true)) to pass remote = false for
tests named send_to_local_* and delegated_send_local_* (and the other affected
invocations), ensuring the local-send path in send_from is executed while
keeping PRELOADED_ADDRESS and other arguments unchanged.

---

Nitpick comments:
In `@tests/common/calibnet_wallet_helpers.rs`:
- Around line 127-130: The polling loops currently sleep before the first check
(using POLL_DELAY in the for i in 1..=POLL_RETRIES loop), which adds unnecessary
delay; update the loop(s) in tests/common/calibnet_wallet_helpers.rs (the loop
around the check() call and the similar occurrence at the region noted around
lines 262-264) to call check() immediately and return on success, and move
tokio::time::sleep(POLL_DELAY).await to run only between retries (e.g., after a
failed check and not on the final iteration) so the first attempt is immediate
and subsequent attempts are delayed.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f56951c0-4974-48c8-9313-4b1dd6cd5e74

📥 Commits

Reviewing files that changed from the base of the PR and between fa086b1 and b942e69.

📒 Files selected for processing (5)
  • .github/workflows/forest.yml
  • scripts/tests/calibnet_delegated_wallet_check.sh
  • scripts/tests/calibnet_wallet_check.sh
  • tests/calibnet_wallet.rs
  • tests/common/calibnet_wallet_helpers.rs
💤 Files with no reviewable changes (2)
  • scripts/tests/calibnet_delegated_wallet_check.sh
  • .github/workflows/forest.yml

Comment thread tests/calibnet_wallet.rs Outdated
Copy link
Copy Markdown
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: 1

🧹 Nitpick comments (2)
tests/common/calibnet_wallet_helpers.rs (2)

120-148: ⚡ Quick win

send_from uses std::thread::sleep — blocks the tokio worker thread if called from async test code.

std::thread::sleep(SEND_RETRY_DELAY) with a 15-second delay will park the OS thread. When called inside a #[tokio::test] body, this starves the runtime of a worker thread for up to (SEND_RETRIES - 1) * 15s = 30s. Replace with tokio::time::sleep and make the function async.

♻️ Convert `send_from` to async
-pub fn send_from(from: &str, to: &str, amount: &str, backend: Backend) -> anyhow::Result<String> {
+pub async fn send_from(from: &str, to: &str, amount: &str, backend: Backend) -> anyhow::Result<String> {
     let args = ["send", "--from", from, to, amount];
     let mut attempt = 1;
     loop {
-        match wallet(backend, &args) {
+        match wallet(backend, &args).await {
             Ok(out) => return Ok(out),
             Err(e) if attempt < SEND_RETRIES && is_min_gas_price_error(&e) => {
                 eprintln!(
                     "send {from} -> {to} hit min-gas-price floor on attempt {attempt}/{SEND_RETRIES}, retrying"
                 );
-                std::thread::sleep(SEND_RETRY_DELAY);
+                tokio::time::sleep(SEND_RETRY_DELAY).await;
                 attempt += 1;
             }
             Err(e) => return Err(e),
         }
     }
 }

(Requires wallet to also be async per the previous comment's suggestion.)

🤖 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 `@tests/common/calibnet_wallet_helpers.rs` around lines 120 - 148, The
send_from function currently blocks the tokio runtime by calling
std::thread::sleep; change send_from to an async function (pub async fn
send_from(...)) and replace std::thread::sleep(SEND_RETRY_DELAY) with
tokio::time::sleep(SEND_RETRY_DELAY).await; also propagate async changes to
wallet by calling an async wallet(backend, &args).await (update its signature to
async if not already) and update all callers/tests to await send_from; keep the
retry logic and is_min_gas_price_error unchanged.

74-94: ⚡ Quick win

Blocking subprocess call inside async poll loop blocks a tokio worker thread.

run_wallet_raw uses std::process::Command::output() — a blocking I/O call. It is invoked synchronously via balance()wallet()run_wallet_raw() inside the synchronous closure passed to the async poll function. Each check() call in poll blocks the tokio worker thread for the subprocess duration without yielding.

The idiomatic fix is to use tokio::process::Command in run_wallet_raw (making it async), or wrap the synchronous call with tokio::task::spawn_blocking at the call sites. Based on coding guidelines: use tokio::task::spawn_blocking for blocking operations called from async contexts.

♻️ Minimal fix: wrap blocking call in `run_wallet_raw`
-pub fn run_wallet_raw(backend: Backend, args: &[&str]) -> anyhow::Result<Vec<u8>> {
-    let _guard = (backend == Backend::Local).then(|| LOCAL_KEYSTORE_LOCK.lock());
-
-    let mut full = Vec::with_capacity(backend.extra_args().len() + args.len());
-    full.extend_from_slice(backend.extra_args());
-    full.extend_from_slice(args);
-
-    let output = Command::new("forest-wallet")
-        .args(&full)
-        .output()
-        .context("failed to spawn `forest-wallet`")?;
+pub async fn run_wallet_raw(backend: Backend, args: &[&str]) -> anyhow::Result<Vec<u8>> {
+    let extra: &[&str] = backend.extra_args();
+    let mut full: Vec<String> = Vec::with_capacity(extra.len() + args.len());
+    full.extend(extra.iter().map(|s| s.to_string()));
+    full.extend(args.iter().map(|s| s.to_string()));
+
+    let _guard = (backend == Backend::Local).then(|| LOCAL_KEYSTORE_LOCK.lock());
+    let output = tokio::process::Command::new("forest-wallet")
+        .args(&full)
+        .output()
+        .await
+        .context("failed to spawn `forest-wallet`")?;

This also requires making wallet, balance, and derived helpers async fn, and updating poll's closure bound to async.

Alternatively, keep the synchronous API and wrap calls in tokio::task::spawn_blocking at the poll level.

Also applies to: 153-165

🤖 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 `@tests/common/calibnet_wallet_helpers.rs` around lines 74 - 94, The blocking
std::process::Command::output() in run_wallet_raw is being called inside async
poll code and must not block a tokio worker — change run_wallet_raw to perform
the blocking subprocess on a blocking thread: make run_wallet_raw an async fn
and wrap the existing Command::new(...).output() call inside
tokio::task::spawn_blocking (await the JoinHandle and propagate errors), then
update the callers wallet() and balance() to be async and adjust the closure
passed into poll/check to be async so it can await balance()/wallet();
alternatively if you prefer to keep run_wallet_raw sync, wrap the current
run_wallet_raw(...) calls at the poll/check call sites with
tokio::task::spawn_blocking(), but do not leave std::process::Command::output()
running on the tokio worker thread.
🤖 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 `@tests/common/calibnet_wallet_helpers.rs`:
- Line 192: The global HTTP client HTTP is created with reqwest::Client::new()
which has no timeout and can hang tests; change the initialization of the static
LazyLock<reqwest::Client> named HTTP to use reqwest::Client::builder() with a
per-request timeout (e.g. Duration::from_secs(30) or configurable from an env
var) so rpc_call and rpc_call_opt cannot block indefinitely; add the necessary
std::time::Duration import and ensure the builder finishes with
.build().expect(...) so the static still constructs reliably.

---

Nitpick comments:
In `@tests/common/calibnet_wallet_helpers.rs`:
- Around line 120-148: The send_from function currently blocks the tokio runtime
by calling std::thread::sleep; change send_from to an async function (pub async
fn send_from(...)) and replace std::thread::sleep(SEND_RETRY_DELAY) with
tokio::time::sleep(SEND_RETRY_DELAY).await; also propagate async changes to
wallet by calling an async wallet(backend, &args).await (update its signature to
async if not already) and update all callers/tests to await send_from; keep the
retry logic and is_min_gas_price_error unchanged.
- Around line 74-94: The blocking std::process::Command::output() in
run_wallet_raw is being called inside async poll code and must not block a tokio
worker — change run_wallet_raw to perform the blocking subprocess on a blocking
thread: make run_wallet_raw an async fn and wrap the existing
Command::new(...).output() call inside tokio::task::spawn_blocking (await the
JoinHandle and propagate errors), then update the callers wallet() and balance()
to be async and adjust the closure passed into poll/check to be async so it can
await balance()/wallet(); alternatively if you prefer to keep run_wallet_raw
sync, wrap the current run_wallet_raw(...) calls at the poll/check call sites
with tokio::task::spawn_blocking(), but do not leave
std::process::Command::output() running on the tokio worker thread.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: acde64a4-1e8e-4efc-90b8-a95a5264725d

📥 Commits

Reviewing files that changed from the base of the PR and between e23f77c and 90cd130.

📒 Files selected for processing (6)
  • .github/workflows/forest.yml
  • mise.toml
  • scripts/tests/calibnet_wallet_check.sh
  • scripts/tests/harness.sh
  • tests/calibnet_wallet.rs
  • tests/common/calibnet_wallet_helpers.rs
💤 Files with no reviewable changes (1)
  • scripts/tests/calibnet_wallet_check.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/calibnet_wallet.rs

Comment thread tests/common/calibnet_wallet_helpers.rs Outdated
Copy link
Copy Markdown
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: 1

🧹 Nitpick comments (1)
.github/workflows/forest.yml (1)

264-271: cargo test compiles from scratch in this job — may be tight against the 30-minute timeout

The job downloads only the pre-built forest* binaries from build-ubuntu; the calibnet_wallet test binary is compiled fresh here. With a cold sccache (first run, or cache miss), compilation plus test execution could approach the SCRIPT_TIMEOUT_MINUTES limit. This is purely an operational concern — if it becomes a problem, consider either: (a) uploading Cargo build cache artifacts from build-ubuntu, or (b) increasing the timeout for this specific step.

🤖 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 @.github/workflows/forest.yml around lines 264 - 271, The "Wallet commands
check" job step may recompile the calibnet_wallet test from scratch and risk
hitting the 30-minute SCRIPT_TIMEOUT_MINUTES limit; update this step to avoid
cold Cargo builds by either (A) restoring/uploading Cargo build cache/artifacts
from the earlier build job (e.g., export/import target and Cargo registry/cache
or the compiled calibnet_wallet binary from the "build-ubuntu" job) so the test
binary isn't rebuilt, or (B) increase the timeout specifically for this step
(the step named "Wallet commands check") by raising timeout-minutes to a larger
value to accommodate a full cargo build and test run.
🤖 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 `@scripts/tests/harness.sh`:
- Line 159: The line exporting PRELOADED_ADDRESS masks the exit status of the
command substitution; change it to run the import command and assign its output
to PRELOADED_ADDRESS first (e.g., run "$FOREST_WALLET_PATH import
preloaded_wallet.key" and capture the output), check the command's exit status
and fail early if it failed, and only then export PRELOADED_ADDRESS so failures
in FOREST_WALLET_PATH or the import are not silenced; update references to
PRELOADED_ADDRESS accordingly in the script.

---

Nitpick comments:
In @.github/workflows/forest.yml:
- Around line 264-271: The "Wallet commands check" job step may recompile the
calibnet_wallet test from scratch and risk hitting the 30-minute
SCRIPT_TIMEOUT_MINUTES limit; update this step to avoid cold Cargo builds by
either (A) restoring/uploading Cargo build cache/artifacts from the earlier
build job (e.g., export/import target and Cargo registry/cache or the compiled
calibnet_wallet binary from the "build-ubuntu" job) so the test binary isn't
rebuilt, or (B) increase the timeout specifically for this step (the step named
"Wallet commands check") by raising timeout-minutes to a larger value to
accommodate a full cargo build and test run.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7f209665-b51c-4532-bfe2-f85bbb8cc7bc

📥 Commits

Reviewing files that changed from the base of the PR and between e23f77c and 9095e83.

📒 Files selected for processing (6)
  • .github/workflows/forest.yml
  • mise.toml
  • scripts/tests/calibnet_wallet_check.sh
  • scripts/tests/harness.sh
  • tests/calibnet_wallet.rs
  • tests/common/calibnet_wallet_helpers.rs
💤 Files with no reviewable changes (1)
  • scripts/tests/calibnet_wallet_check.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/calibnet_wallet.rs
  • tests/common/calibnet_wallet_helpers.rs

Comment thread scripts/tests/harness.sh Outdated
Copy link
Copy Markdown
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

🤖 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 `@mise.toml`:
- Line 219: The test invocation now runs with default parallel threads causing
nonce-safety races for tests in calibnet_wallet.rs that reuse PRELOADED_ADDRESS;
update the cargo test command invocation (the line containing "cargo test
--profile quick-test --test calibnet_wallet -- --ignored --nocapture") to
include "--test-threads=1" so tests run single-threaded and avoid concurrent
sends from PRELOADED_ADDRESS.

In `@tests/calibnet_wallet.rs`:
- Around line 65-77: Tests that call send_from(&PRELOADED_ADDRESS, ...) can race
on nonce when Backend::Local uses the non-atomic MpoolGetNonce → sign →
MpoolPush flow (MpoolGetNonce / MpoolPush), causing duplicate nonces; fix by
either serializing test execution (add --test-threads=1 to the test invocation
in mise.toml) or change the local wallet send path to use the same atomic push
used by remote (MpoolPushMessage) — if you choose the latter, update the
forest-wallet send implementation to call MpoolPushMessage for Backend::Local
and adapt its API/signing flow so the keystore signing is preserved (modify the
send function to accept pre-signed or signing-callback semantics compatible with
MpoolPushMessage).
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 47e4ba02-8a0f-4481-9825-cb5d10292527

📥 Commits

Reviewing files that changed from the base of the PR and between e23f77c and 65e952c.

📒 Files selected for processing (6)
  • .github/workflows/forest.yml
  • mise.toml
  • scripts/tests/calibnet_wallet_check.sh
  • scripts/tests/harness.sh
  • tests/calibnet_wallet.rs
  • tests/common/calibnet_wallet_helpers.rs
💤 Files with no reviewable changes (1)
  • scripts/tests/calibnet_wallet_check.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/common/calibnet_wallet_helpers.rs

Comment thread mise.toml
Comment thread tests/calibnet_wallet.rs
Copy link
Copy Markdown
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: 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 `@mise.toml`:
- Around line 216-218: The script enables xtrace which can leak the preloaded
private key when calling forest_wallet_init with the usage_preloaded_key
variable; remove the xtrace flag or disable tracing around that call by changing
the initial shell flags so they do not include -x (e.g., use set -euo pipefail)
or temporarily turn off tracing before invoking forest_wallet_init and re-enable
it afterwards, ensuring forest_wallet_init and the usage_preloaded_key value are
never printed to the logs.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7d88333a-c329-48c7-9f19-981047054a71

📥 Commits

Reviewing files that changed from the base of the PR and between e23f77c and e89d6b2.

📒 Files selected for processing (6)
  • .github/workflows/forest.yml
  • mise.toml
  • scripts/tests/calibnet_wallet_check.sh
  • scripts/tests/harness.sh
  • tests/calibnet_wallet.rs
  • tests/common/calibnet_wallet_helpers.rs
💤 Files with no reviewable changes (1)
  • scripts/tests/calibnet_wallet_check.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/forest.yml
  • tests/common/calibnet_wallet_helpers.rs

Comment thread mise.toml Outdated
Copy link
Copy Markdown
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: 1

♻️ Duplicate comments (1)
mise.toml (1)

219-219: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Serialize this test target to avoid nonce races between cases.

calibnet_wallet still runs with the default cargo test thread count, but several ignored cases reuse the same funded sender. That makes the Rust replacement less stable than the old sequential shell flow and can trigger nondeterministic local-wallet send failures. Please add --test-threads=1 here, or otherwise serialize this target.

🛡️ Minimal fix
-cargo test --profile quick-test --test calibnet_wallet -- --ignored --nocapture
+cargo test --profile quick-test --test calibnet_wallet -- --ignored --nocapture --test-threads=1
🤖 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 `@mise.toml` at line 219, The calibnet_wallet test invocation in mise.toml runs
with parallel threads causing nonce races; update the cargo test command that
targets "calibnet_wallet" to serialize execution by adding --test-threads=1
(i.e., change the existing line "cargo test --profile quick-test --test
calibnet_wallet -- --ignored --nocapture" to include --test-threads=1) so the
ignored cases reuse the funded sender sequentially and avoid nondeterministic
wallet send failures.
🧹 Nitpick comments (1)
tests/common/calibnet_wallet_helpers.rs (1)

81-84: ⚡ Quick win

Honor FOREST_WALLET_PATH here for parity with the harness.

This hardcodes forest-wallet, so overriding FOREST_WALLET_PATH in scripts/tests/harness.sh no longer affects the Rust tests. Reading the env var here keeps the new test path aligned with the existing harness behavior.

♻️ Minimal adjustment
-    let output = Command::new("forest-wallet")
+    let wallet_bin = std::env::var("FOREST_WALLET_PATH")
+        .ok()
+        .filter(|value| !value.is_empty())
+        .unwrap_or_else(|| "forest-wallet".to_owned());
+    let output = Command::new(&wallet_bin)
         .args(&full)
         .output()
         .context("failed to spawn `forest-wallet`")?;
🤖 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 `@tests/common/calibnet_wallet_helpers.rs` around lines 81 - 84, The test
hardcodes "forest-wallet" in the Command::new call so FOREST_WALLET_PATH is
ignored; change the Command::new invocation in
tests/common/calibnet_wallet_helpers.rs to read the executable path from the
FOREST_WALLET_PATH environment variable (e.g., via std::env::var or var_os) and
fall back to "forest-wallet" if the env var is not set, then pass that path to
Command::new instead of the literal "forest-wallet" so the harness override is
honored.
🤖 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 `@tests/common/calibnet_wallet_helpers.rs`:
- Around line 153-165: The poll function (and the similar retry block at
275-289) currently uses the `?` operator inside the retry loop which aborts on
the first transient CLI/RPC error; change the loop to capture errors from
`check()` instead of propagating them: call `check()` inside the loop, on
Ok(Some(v)) return Ok(v), on Ok(None) continue retrying, on Err(e) store the
error into a `last_err` variable and continue (do not return); after the retries
are exhausted, if `last_err` is Some(err) return that error (or wrap it with
context), otherwise bail with the existing timeout message; update both `poll`
and the other retry helper at lines 275-289 to use this same pattern so
transient failures are retried.

---

Duplicate comments:
In `@mise.toml`:
- Line 219: The calibnet_wallet test invocation in mise.toml runs with parallel
threads causing nonce races; update the cargo test command that targets
"calibnet_wallet" to serialize execution by adding --test-threads=1 (i.e.,
change the existing line "cargo test --profile quick-test --test calibnet_wallet
-- --ignored --nocapture" to include --test-threads=1) so the ignored cases
reuse the funded sender sequentially and avoid nondeterministic wallet send
failures.

---

Nitpick comments:
In `@tests/common/calibnet_wallet_helpers.rs`:
- Around line 81-84: The test hardcodes "forest-wallet" in the Command::new call
so FOREST_WALLET_PATH is ignored; change the Command::new invocation in
tests/common/calibnet_wallet_helpers.rs to read the executable path from the
FOREST_WALLET_PATH environment variable (e.g., via std::env::var or var_os) and
fall back to "forest-wallet" if the env var is not set, then pass that path to
Command::new instead of the literal "forest-wallet" so the harness override is
honored.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5627ba94-4804-4ce5-ab6b-46821ab60e41

📥 Commits

Reviewing files that changed from the base of the PR and between e23f77c and b06c190.

📒 Files selected for processing (6)
  • .github/workflows/forest.yml
  • mise.toml
  • scripts/tests/calibnet_wallet_check.sh
  • scripts/tests/harness.sh
  • tests/calibnet_wallet.rs
  • tests/common/calibnet_wallet_helpers.rs
💤 Files with no reviewable changes (1)
  • scripts/tests/calibnet_wallet_check.sh

Comment thread tests/common/calibnet_wallet_helpers.rs
@sudo-shashank sudo-shashank marked this pull request as ready for review May 7, 2026 10:03
@sudo-shashank sudo-shashank requested a review from a team as a code owner May 7, 2026 10:03
@sudo-shashank sudo-shashank requested review from LesnyRumcajs and hanabi1224 and removed request for a team May 7, 2026 10:03
Copy link
Copy Markdown
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.

♻️ Duplicate comments (1)
tests/common/calibnet_wallet_helpers.rs (1)

153-165: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Transient check() errors still abort the poll loop immediately (unresolved from prior review).

check()? at line 160 propagates the first error returned by the closure, so a single transient forest-wallet process failure (daemon briefly unavailable, spawn error, etc.) fails the test immediately instead of retrying. The original bash scripts continued the sleep loop on non-zero exits. The same issue applies to poll_until_state_search_msg at line 281 (await?).

🛡️ Suggested fix
 pub async fn poll<F>(what: &str, mut check: F) -> anyhow::Result<String>
 where
     F: FnMut() -> anyhow::Result<Option<String>>,
 {
+    let mut last_err: Option<anyhow::Error> = None;
     for i in 1..=POLL_RETRIES {
         eprintln!("Polling {what} {i}/{POLL_RETRIES}");
         tokio::time::sleep(POLL_DELAY).await;
-        if let Some(value) = check()? {
-            return Ok(value);
+        match check() {
+            Ok(Some(value)) => return Ok(value),
+            Ok(None) => {}
+            Err(e) => {
+                eprintln!("Polling {what}: transient error on attempt {i}: {e}");
+                last_err = Some(e);
+            }
         }
     }
-    bail!("Timed out waiting for {what} after {POLL_RETRIES} retries")
+    if let Some(e) = last_err {
+        return Err(e).with_context(|| format!("last error while polling {what}"));
+    }
+    bail!("Timed out waiting for {what} after {POLL_RETRIES} retries")
 }

Apply the same pattern to poll_until_state_search_msg:

     for i in 1..=SEARCH_MSG_RETRIES {
         tokio::time::sleep(SEARCH_MSG_DELAY).await;
         eprintln!("StateSearchMsg polling {msg_cid} attempt {i}/{SEARCH_MSG_RETRIES}");
         let params = json!([[], { "/": msg_cid }, 800_i64, true]);
-        if rpc_call_opt("Filecoin.StateSearchMsg", params)
-            .await?
-            .is_some()
-        {
-            return Ok(());
+        match rpc_call_opt("Filecoin.StateSearchMsg", params).await {
+            Ok(Some(_)) => return Ok(()),
+            Ok(None) => {}
+            Err(e) => eprintln!("StateSearchMsg transient error on attempt {i}: {e}"),
         }
     }
🤖 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 `@tests/common/calibnet_wallet_helpers.rs` around lines 153 - 165, The poll
function (pub async fn poll) currently uses check()? which propagates any error
from the closure and aborts retries; change it to call check() and match on its
Result so transient errors are treated like a missing value (log or ignore and
continue sleeping/retrying) instead of returning Err immediately, i.e., map
Err(_) to continue the loop and only return Ok(value) when check() yields
Ok(Some(_)), and apply the same pattern to poll_until_state_search_msg so its
await? does not propagate transient errors but instead retries until
POLL_RETRIES are exhausted.
🤖 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.

Duplicate comments:
In `@tests/common/calibnet_wallet_helpers.rs`:
- Around line 153-165: The poll function (pub async fn poll) currently uses
check()? which propagates any error from the closure and aborts retries; change
it to call check() and match on its Result so transient errors are treated like
a missing value (log or ignore and continue sleeping/retrying) instead of
returning Err immediately, i.e., map Err(_) to continue the loop and only return
Ok(value) when check() yields Ok(Some(_)), and apply the same pattern to
poll_until_state_search_msg so its await? does not propagate transient errors
but instead retries until POLL_RETRIES are exhausted.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 35263da2-460c-4f7e-ae71-950528fcd68d

📥 Commits

Reviewing files that changed from the base of the PR and between e23f77c and b06c190.

📒 Files selected for processing (6)
  • .github/workflows/forest.yml
  • mise.toml
  • scripts/tests/calibnet_wallet_check.sh
  • scripts/tests/harness.sh
  • tests/calibnet_wallet.rs
  • tests/common/calibnet_wallet_helpers.rs
💤 Files with no reviewable changes (1)
  • scripts/tests/calibnet_wallet_check.sh

@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 64.13%. Comparing base (6191297) to head (f0c8aa3).
✅ All tests successful. No failed tests found.

Additional details and impacted files

see 7 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6191297...f0c8aa3. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Member

@LesnyRumcajs LesnyRumcajs left a comment

Choose a reason for hiding this comment

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

The test themselves shouldn't use the ? shorthand; in case of a failure the exact line which failed won't propagate and will make things more difficult to debug. unwrap should be used there and the tests shouldn't return Result.

Copy link
Copy Markdown
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)
tests/calibnet_wallet.rs (1)

27-33: ⚡ Quick win

Use anyhow::Result<()> with .context() throughout this test file instead of .unwrap() and .expect() panics.

The file has 33 instances of panic-style error handling (.unwrap() and .expect()). Converting test functions to return Result and using ? with .context() makes failures more debuggable and aligns with the repo's Rust guideline for error handling.

Suggested pattern
+use anyhow::Context;
@@
-async fn export_import_roundtrip(#[case] backend: Backend) {
-    let addr = wallet(backend, &["new"]).unwrap();
+async fn export_import_roundtrip(#[case] backend: Backend) -> anyhow::Result<()> {
+    let addr = wallet(backend, &["new"]).context("wallet new failed")?;
@@
-    let imported = wallet(backend, &["import", path]).unwrap();
+    let imported = wallet(backend, &["import", path]).context("wallet import failed")?;
@@
-}
+    Ok(())
+}

Apply to all test functions and the funded_delegated_addr helper.

🤖 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 `@tests/calibnet_wallet.rs` around lines 27 - 33, Change these test functions
(e.g., export_import_roundtrip) and the funded_delegated_addr helper to return
anyhow::Result<()> instead of panicking; replace all occurrences of
.unwrap()/.expect() in tests with the ? operator and add .context("descriptive
message") where helpful to attach context to failures (for example when calling
wallet(...), export_to_temp_file(...), path().to_str(), etc.), and update
imports to use anyhow::Context so the file compiles and errors propagate instead
of panicking.
🤖 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 `@tests/calibnet_wallet.rs`:
- Around line 27-33: Change these test functions (e.g., export_import_roundtrip)
and the funded_delegated_addr helper to return anyhow::Result<()> instead of
panicking; replace all occurrences of .unwrap()/.expect() in tests with the ?
operator and add .context("descriptive message") where helpful to attach context
to failures (for example when calling wallet(...), export_to_temp_file(...),
path().to_str(), etc.), and update imports to use anyhow::Context so the file
compiles and errors propagate instead of panicking.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 69d6f2c3-e049-436e-9091-9555b3aefcff

📥 Commits

Reviewing files that changed from the base of the PR and between b06c190 and b4ad326.

📒 Files selected for processing (1)
  • tests/calibnet_wallet.rs

Comment thread tests/common/calibnet_wallet_helpers.rs Outdated
Comment thread tests/common/calibnet_wallet_helpers.rs Outdated
Comment thread tests/common/calibnet_wallet_helpers.rs Outdated
Comment thread tests/common/calibnet_wallet_helpers.rs
Comment thread tests/calibnet_wallet.rs Outdated
Comment thread mise.toml
set -euo pipefail
source ./scripts/tests/harness.sh
forest_wallet_init "${usage_preloaded_key?}"
cargo test --profile quick-test --test calibnet_wallet -- --ignored --nocapture
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I completely miss your usage of ignored in these tests. Please elaborate.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

since these test require a running calibnet node, ignored is used so that these test doesn't get executed as a part of the default test suite

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.

Convert calibnet wallet check bash scripts to Rust

2 participants