Skip to content

Conversation

@troian
Copy link
Member

@troian troian commented Oct 21, 2025

Description

Closes: #XXXX


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow-up issues.

I have...

  • included the correct type prefix in the PR title
  • added ! to the type prefix if API or client breaking change
  • targeted the correct branch (see PR Targeting)
  • provided a link to the relevant issue or specification
  • included the necessary unit and integration tests
  • added a changelog entry to CHANGELOG.md
  • included comments for documenting Go code
  • updated the relevant documentation or specification
  • reviewed "Files changed" and left comments if necessary
  • confirmed all CI checks have passed

@troian troian requested a review from a team as a code owner October 21, 2025 17:18
@github-actions github-actions bot added the C:CLI label Oct 21, 2025
@coderabbitai
Copy link

coderabbitai bot commented Oct 21, 2025

Walkthrough

Changed testnet init and CLI config to support per-account balances, explicit validator status and delegations, and stronger error handling; validator voting power is computed from delegations and ApplyAndReturnValidatorSetUpdates errors are now checked and panicked on.

Changes

Cohort / File(s) Summary
Core: export error handling
app/export.go
Capture the error returned by ApplyAndReturnValidatorSetUpdates(ctx) and panic if non-nil (previously ignored).
Core: testnet init and types
app/testnet.go
Added TestnetAccount and TestnetDelegation types; added Status and Delegations fields to TestnetValidator; changed TestnetConfig.Accounts to []TestnetAccount; mint/distribute uses per-account Balances; validators created with config-provided Status, Commission, MinSelfDelegation, Moniker; delegations applied after validator creation; panics on creation/delegation/apply errors.
CLI config types
cmd/akash/cmd/testnetify/config.go
TestnetValidator: removed Bonded (bool), added Status (stakingtypes.BondStatus) and Delegations ([]akash.TestnetDelegation); TestnetConfig.Accounts now []akash.TestnetAccount.
CLI: testnetify logic
cmd/akash/cmd/testnetify/testnetify.go
Encode checksum via hex.EncodeToString(...) when loading state; assign default balances if none provided; populate validators with Status and Delegations; compute validator voting power by summing delegations (converted using DefaultPowerReduction) and use that vp for validator voting power (replacing prior hardcoded value).

Sequence Diagram(s)

sequenceDiagram
    participant CLI as testnetify
    participant AppInit as InitAkashAppForTestnet
    participant Bank as BankKeeper
    participant Staking as StakingKeeper
    participant Apply as ApplyAndReturnValidatorSetUpdates

    CLI->>AppInit: provide TestnetConfig (accounts, validators)
    AppInit->>Bank: Mint balances for each `TestnetAccount`
    Bank-->>AppInit: balances minted
    AppInit->>Staking: Create validators with Status, Commission, MinSelfDelegation
    Staking-->>AppInit: validators created (Tokens/DelegatorShares set from config)
    AppInit->>Staking: Apply delegations from `TestnetValidator.Delegations`
    Staking-->>AppInit: delegations applied
    AppInit->>Apply: ApplyAndReturnValidatorSetUpdates(ctx)
    alt success
        Apply-->>AppInit: validator set updated
    else error
        Apply--xAppInit: returns error
        AppInit-->>AppInit: panic (abort initialization)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nibble configs, coins in tow,

Validators wake with status aglow,
Delegations counted, voting grown,
Errors found — a loud rabbit groan!
New balances hop, the testnet's sown. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description Check ❓ Inconclusive The PR description consists entirely of the default pull request template with placeholder text ("Closes: #XXXX") and an unchecked Author Checklist. There is no substantive description of the code changes, objectives, or files critical to review. While the description is not off-topic in the sense of being misleading, it effectively provides no information about what the changeset accomplishes and therefore does not meaningfully describe any part of the changeset.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "refactor(cmd/testnetify): add multi-account support" is clearly related to the changeset and accurately captures a significant aspect of the changes. The raw summary confirms that the modifications introduce TestnetAccount struct, change TestnetConfig.Accounts field type, and modify InitAkashAppForTestnet to handle account balances and delegations. The title focuses on the multi-account support feature as the primary change, which is a real and important part of the refactoring. While the changes also include delegation support and validator status handling, the title does not need to cover every detail of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch testnetify

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.

🔧 golangci-lint (2.5.0)

Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions
The command is terminated due to an error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions


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

Copy link

@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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/testnet.go (1)

209-212: Nil-guard GOV voting params to avoid panic.

If VotingParams is omitted in config, this will nil-deref.

Apply this diff:

- voteParams := app.Keepers.Cosmos.Gov.GetVotingParams(ctx)
- voteParams.VotingPeriod = tcfg.Gov.VotingParams.VotingPeriod.Duration
- app.Keepers.Cosmos.Gov.SetVotingParams(ctx, voteParams)
+ if tcfg.Gov.VotingParams != nil {
+   voteParams := app.Keepers.Cosmos.Gov.GetVotingParams(ctx)
+   voteParams.VotingPeriod = tcfg.Gov.VotingParams.VotingPeriod.Duration
+   app.Keepers.Cosmos.Gov.SetVotingParams(ctx, voteParams)
+ }
🧹 Nitpick comments (6)
app/export.go (1)

190-193: Good: stop ignoring staking updates error; consider adding context.

Capturing the error is correct. To aid debugging, wrap with context (e.g., panic(fmt.Errorf("staking.ApplyAndReturnValidatorSetUpdates: %w", err))).

cmd/akash/cmd/testnetify/testnetify.go (2)

130-140: Validate defaults: ensure tokens fit int64 and shares are non‑negative.

Prevent invalid/overflow values early; fail fast with a clear error.

Apply inline checks:

 for i, val := range cfg.Validators {
   if val.Tokens == nil {
     tk := sdk.NewInt(900000000000000)
     cfg.Validators[i].Tokens = &tk
   }
   if val.DelegatorShares == nil {
     shares := sdk.MustNewDecFromStr("10000000")
     cfg.Validators[i].DelegatorShares = &shares
   }
+  // Sanity checks
+  if cfg.Validators[i].Tokens.IsNegative() || cfg.Validators[i].Tokens.BigInt().BitLen() >= 63 {
+    return fmt.Errorf("validator %q tokens must be within [0, 2^63-1]", val.Moniker)
+  }
+  if cfg.Validators[i].DelegatorShares.IsNegative() {
+    return fmt.Errorf("validator %q delegator_shares must be non-negative", val.Moniker)
+  }
 }

367-377: Defensive: guard against nil Tokens/Shares before dereference.

Defaults are set earlier, but add a guard to avoid future regressions if code is refactored.

Example:

-      Tokens:            *val.Tokens,
-      DelegatorShares:   *val.DelegatorShares,
+      Tokens:            func() sdk.Int { if val.Tokens == nil { return sdk.ZeroInt() }; return *val.Tokens }(),
+      DelegatorShares:   func() sdk.Dec { if val.DelegatorShares == nil { return sdk.ZeroDec() }; return *val.DelegatorShares }(),
app/testnet.go (3)

48-51: Prefer sdk.Coins for balances to avoid conversions and ensure canonicalization.

sdk.Coins carries invariants (sorted, non-dup) and integrates better with bank APIs.

Apply this diff:

 type TestnetAccount struct {
   Address  sdk.AccAddress `json:"address"`
-  Balances []sdk.Coin     `json:"balances"`
+  Balances sdk.Coins      `json:"balances"`
 }

219-227: Adjust BANK mint path to new type (and avoid redundant NewCoins).

If Balances is sdk.Coins, you can use it directly; fallback still uses NewCoins.

Apply this diff:

-  var coins sdk.Coins
-  if len(account.Balances) > 0 {
-    coins = sdk.NewCoins(account.Balances...)
-  } else {
-    coins = sdk.NewCoins(
+  var coins sdk.Coins
+  if len(account.Balances) > 0 {
+    coins = account.Balances
+  } else {
+    coins = sdk.NewCoins(
       sdk.NewInt64Coin("uakt", 1000000000000),
       sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000), // axlUSDC
     )
   }

194-197: Call ApplyAndReturnValidatorSetUpdates once after inserting all validators.

Invoking it inside the loop is unnecessary and increases churn; move it after the loop for clarity and fewer state transitions.

Apply this diff:

-    _, err = app.Keepers.Cosmos.Staking.ApplyAndReturnValidatorSetUpdates(ctx)
-    if err != nil {
-      panic(err)
-    }
@@
 }
+// After all validators are created, update the validator set once.
+_, err = app.Keepers.Cosmos.Staking.ApplyAndReturnValidatorSetUpdates(ctx)
+if err != nil {
+  panic(err)
+}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ab1cd9 and 8942694.

📒 Files selected for processing (4)
  • app/export.go (1 hunks)
  • app/testnet.go (5 hunks)
  • cmd/akash/cmd/testnetify/config.go (1 hunks)
  • cmd/akash/cmd/testnetify/testnetify.go (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
app/testnet.go (1)
cmd/akash/cmd/testnetify/config.go (1)
  • AccAddress (31-33)
cmd/akash/cmd/testnetify/config.go (1)
app/testnet.go (2)
  • TestnetValidator (22-32)
  • TestnetAccount (48-51)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: coverage
  • GitHub Check: tests
  • GitHub Check: release-dry-run
  • GitHub Check: shellcheck
  • GitHub Check: sims
  • GitHub Check: lint
  • GitHub Check: build-macos
  • GitHub Check: tests
  • GitHub Check: network-upgrade
  • GitHub Check: lint
  • GitHub Check: release-dry-run
  • GitHub Check: sims
  • GitHub Check: build-bins
  • GitHub Check: coverage
  • GitHub Check: build-macos
🔇 Additional comments (1)
cmd/akash/cmd/testnetify/testnetify.go (1)

324-324: LGTM: hex-encoding updated genesis checksum for LoadStateFromDBOrGenesisDocProvider.

Comment on lines 119 to 129
for i, acc := range cfg.Accounts {
if len(acc.Balances) > 0 {
cfg.Accounts[i].Balances = sdk.NewCoins(acc.Balances...)
} else {
cfg.Accounts[i].Balances = sdk.NewCoins(
sdk.NewInt64Coin("uakt", 1000000000000),
sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000), // axlUSDC
)
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix type mismatch when assigning balances.

cfg.Accounts[i].Balances is []sdk.Coin, while sdk.NewCoins(...) returns sdk.Coins. Use an explicit conversion to avoid compile-time type errors.

Apply this diff:

 for i, acc := range cfg.Accounts {
   if len(acc.Balances) > 0 {
-    cfg.Accounts[i].Balances = sdk.NewCoins(acc.Balances...)
+    cfg.Accounts[i].Balances = []sdk.Coin(sdk.NewCoins(acc.Balances...))
   } else {
-    cfg.Accounts[i].Balances = sdk.NewCoins(
-      sdk.NewInt64Coin("uakt", 1000000000000),
-      sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000), // axlUSDC
-    )
+    cfg.Accounts[i].Balances = []sdk.Coin(sdk.NewCoins(
+      sdk.NewInt64Coin("uakt", 1000000000000),
+      sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000), // axlUSDC
+    ))
   }
 }

Optional: standardize on sdk.Coins in TestnetAccount to avoid future conversions.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for i, acc := range cfg.Accounts {
if len(acc.Balances) > 0 {
cfg.Accounts[i].Balances = sdk.NewCoins(acc.Balances...)
} else {
cfg.Accounts[i].Balances = sdk.NewCoins(
sdk.NewInt64Coin("uakt", 1000000000000),
sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000), // axlUSDC
)
}
}
for i, acc := range cfg.Accounts {
if len(acc.Balances) > 0 {
cfg.Accounts[i].Balances = []sdk.Coin(sdk.NewCoins(acc.Balances...))
} else {
cfg.Accounts[i].Balances = []sdk.Coin(sdk.NewCoins(
sdk.NewInt64Coin("uakt", 1000000000000),
sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000), // axlUSDC
))
}
}
🤖 Prompt for AI Agents
In cmd/akash/cmd/testnetify/testnetify.go around lines 119-128, the code assigns
sdk.NewCoins(...), which returns sdk.Coins, to cfg.Accounts[i].Balances which is
of type []sdk.Coin; perform an explicit conversion to the slice type when
assigning (for example: cfg.Accounts[i].Balances =
[]sdk.Coin(sdk.NewCoins(...))). Update both branches (the existing balances
branch and the default branch) accordingly; optionally consider changing
TestnetAccount.Balances to sdk.Coins to avoid repeated conversions in future.

Comment on lines 479 to 475
Address: val.validatorAddress,
PubKey: val.pubKey,
VotingPower: 900000000000000,
VotingPower: val.Tokens.Int64(),
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Make VotingPower conversion int64‑safe (avoid overflow/negative).

Tokens may exceed int64 or be negative; clamp or normalize before assigning to Validator.VotingPower.

Apply this diff (and add import "math"):

@@
-    newValidators = append(newValidators, &cmttypes.Validator{
-      Address:     val.validatorAddress,
-      PubKey:      val.pubKey,
-      VotingPower: val.Tokens.Int64(),
-    })
+    // Ensure int64-safe voting power
+    var vp int64
+    if val.Tokens.IsNegative() {
+      vp = 0
+    } else if val.Tokens.BigInt().BitLen() >= 63 {
+      vp = math.MaxInt64
+    } else {
+      vp = val.Tokens.Int64()
+    }
+    newValidators = append(newValidators, &cmttypes.Validator{
+      Address:     val.validatorAddress,
+      PubKey:      val.pubKey,
+      VotingPower: vp,
+    })

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In cmd/akash/cmd/testnetify/testnetify.go around lines 479 to 482, the
VotingPower is set using val.Tokens.Int64() which can overflow or be negative;
clamp the value into the int64 range and ensure non‑negative before assigning to
Validator.VotingPower. Replace the direct Int64() call with logic that converts
safely: compute the token value as an int64 (capping at math.MaxInt64 if it
exceeds that, and using 0 if negative), then assign that clamped int64 to
VotingPower; add import "math" to the file.

Copy link

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
cmd/akash/cmd/testnetify/testnetify.go (2)

356-365: Fix operator/consensus address types in appConfig.

Use typed addresses, not raw bytes. This also relies on Operator being ValAddress in config.go.

-    appConfig.Validators = append(appConfig.Validators, akash.TestnetValidator{
-      OperatorAddress:   val.Operator.Bytes(),
-      ConsensusAddress:  pubKey.Address().Bytes(),
+    appConfig.Validators = append(appConfig.Validators, akash.TestnetValidator{
+      OperatorAddress:   val.Operator.ValAddress,
+      ConsensusAddress:  sdktypes.ConsAddress(pubKey.Address().Bytes()),
       ConsensusPubKey:   consensusPubkey,
       Moniker:           val.Moniker,
       Commission:        val.Commission,
       MinSelfDelegation: val.MinSelfDelegation,
       Status:            val.Status,
       Delegations:       val.Delegations,
     })

479-483: Guard against empty validator set before selecting proposer.

Avoid panic when no validators are configured.

-  newValSet := &cmttypes.ValidatorSet{
-    Validators: newValidators,
-    Proposer:   newValidators[0],
-  }
+  if len(newValidators) == 0 {
+    return nil, fmt.Errorf("no validators configured")
+  }
+  newValSet := &cmttypes.ValidatorSet{
+    Validators: newValidators,
+    Proposer:   newValidators[0],
+  }
app/testnet.go (1)

239-241: Nil guard for optional GOV voting params.

tcfg.Gov.VotingParams can be nil; dereferencing will panic.

-  voteParams := app.Keepers.Cosmos.Gov.GetVotingParams(ctx)
-  voteParams.VotingPeriod = tcfg.Gov.VotingParams.VotingPeriod.Duration
-  app.Keepers.Cosmos.Gov.SetVotingParams(ctx, voteParams)
+  if tcfg.Gov.VotingParams != nil {
+    voteParams := app.Keepers.Cosmos.Gov.GetVotingParams(ctx)
+    voteParams.VotingPeriod = tcfg.Gov.VotingParams.VotingPeriod.Duration
+    app.Keepers.Cosmos.Gov.SetVotingParams(ctx, voteParams)
+  }
♻️ Duplicate comments (3)
cmd/akash/cmd/testnetify/config.go (1)

45-45: Align operator address with staking semantics: use ValAddress.

Operator is a validator operator address, not an account address. Switch to ValAddress to avoid accidental Acc/Val mixups and to match app.TestnetValidator.OperatorAddress.

 type TestnetValidator struct {
   Moniker           string                    `json:"moniker"`
-  Operator          AccAddress                `json:"operator"`
+  Operator          ValAddress                `json:"operator"`
   Status            stakingtypes.BondStatus   `json:"status"`
   Commission        stakingtypes.Commission   `json:"commission"`
   MinSelfDelegation sdk.Int                   `json:"min_self_delegation"`
   Home              string                    `json:"home"`
   Delegations       []akash.TestnetDelegation `json:"delegations"`
 }
cmd/akash/cmd/testnetify/testnetify.go (2)

120-129: Normalize Balances type usage; avoid sdk.Coins → []sdk.Coin mismatch.

Current code assigns sdk.Coins to a []sdk.Coin field; this mismatches types and was flagged earlier.

Preferred fix (paired with changing app.TestnetAccount.Balances to sdk.Coins; see app/testnet.go comment):

 for i, acc := range cfg.Accounts {
-  if len(acc.Balances) > 0 {
-    cfg.Accounts[i].Balances = sdk.NewCoins(acc.Balances...)
-  } else {
-    cfg.Accounts[i].Balances = sdk.NewCoins(
+  if len(acc.Balances) > 0 {
+    cfg.Accounts[i].Balances = acc.Balances
+  } else {
+    cfg.Accounts[i].Balances = sdk.NewCoins(
       sdk.NewInt64Coin("uakt", 10000000000000),
       sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000),
-    )
+    )
   }
 }

If you cannot change app.TestnetAccount yet, perform explicit conversion here as a stopgap:

-    cfg.Accounts[i].Balances = sdk.NewCoins(acc.Balances...)
+    cfg.Accounts[i].Balances = []sdk.Coin(sdk.NewCoins(acc.Balances...))
@@
-    cfg.Accounts[i].Balances = sdk.NewCoins(
+    cfg.Accounts[i].Balances = []sdk.Coin(sdk.NewCoins(
       sdk.NewInt64Coin("uakt", 10000000000000),
       sdk.NewInt64Coin("ibc/12C6A0C374171B595A0A9E18B83FA09D295FB1F2D8C6DAA3AC28683471752D84", 1000000000000),
-    )
+    ))

466-475: Make VotingPower int64‑safe; clamp and ignore negatives.

Summing Int64() can overflow or go negative. Clamp to [0, math.MaxInt64].

-    var vp int64
-    for _, del := range val.Delegations {
-      vp += del.Amount.Amount.Quo(sdktypes.DefaultPowerReduction).Int64()
-    }
+    var vp int64
+    for _, del := range val.Delegations {
+      if del.Amount.Amount.IsNegative() {
+        continue
+      }
+      amt := del.Amount.Amount.Quo(sdktypes.DefaultPowerReduction)
+      if amt.IsZero() {
+        continue
+      }
+      if amt.BigInt().BitLen() >= 63 {
+        vp = math.MaxInt64
+        break
+      }
+      a := amt.Int64()
+      if vp > math.MaxInt64-a {
+        vp = math.MaxInt64
+        break
+      }
+      vp += a
+    }

Also add:

 import (
   "bufio"
+  "math"
   "encoding/hex"
🧹 Nitpick comments (2)
cmd/akash/cmd/testnetify/testnetify.go (1)

17-17: Import hygiene: pick one alias for cosmos types.

Both sdk and sdktypes point to the same package. Prefer a single alias for clarity.

Proposed:

  • Keep only sdk "github.com/cosmos/cosmos-sdk/types" and drop sdktypes, updating call sites (DefaultPowerReduction, ConsAddress) accordingly.

Also applies to: 35-35

app/testnet.go (1)

52-56: Optional: add JSON bech32 parsing for Accounts/Delegations.

To allow human‑friendly configs, implement UnmarshalJSON to parse bech32 addresses.

Example (add imports: encoding/json):

func (t *TestnetAccount) UnmarshalJSON(data []byte) error {
  var aux struct {
    Address  string     `json:"address"`
    Balances sdk.Coins  `json:"balances"`
  }
  if err := json.Unmarshal(data, &aux); err != nil { return err }
  addr, err := sdk.AccAddressFromBech32(aux.Address); if err != nil { return err }
  t.Address, t.Balances = addr, aux.Balances
  return nil
}

func (t *TestnetDelegation) UnmarshalJSON(data []byte) error {
  var aux struct {
    Address string   `json:"address"`
    Amount  sdk.Coin `json:"amount"`
  }
  if err := json.Unmarshal(data, &aux); err != nil { return err }
  addr, err := sdk.AccAddressFromBech32(aux.Address); if err != nil { return err }
  t.Address, t.Amount = addr, aux.Amount
  return nil
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8942694 and e4d6cfa.

📒 Files selected for processing (4)
  • app/export.go (1 hunks)
  • app/testnet.go (4 hunks)
  • cmd/akash/cmd/testnetify/config.go (2 hunks)
  • cmd/akash/cmd/testnetify/testnetify.go (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/export.go
🧰 Additional context used
🧬 Code graph analysis (2)
cmd/akash/cmd/testnetify/config.go (1)
app/testnet.go (2)
  • TestnetDelegation (52-55)
  • TestnetAccount (47-50)
cmd/akash/cmd/testnetify/testnetify.go (1)
testutil/network/network.go (1)
  • Validator (134-153)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: network-upgrade-names
  • GitHub Check: lint
  • GitHub Check: release-dry-run
  • GitHub Check: sims
  • GitHub Check: coverage
  • GitHub Check: tests
  • GitHub Check: build-bins
  • GitHub Check: build-macos
  • GitHub Check: release-dry-run
  • GitHub Check: tests
  • GitHub Check: sims
  • GitHub Check: lint
  • GitHub Check: coverage
  • GitHub Check: build-bins

Comment on lines +47 to +50
type TestnetAccount struct {
Address sdk.AccAddress `json:"address"`
Balances []sdk.Coin `json:"balances"`
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Use sdk.Coins for Balances to match bank APIs.

Bank.MintCoins/SendCoinsFromModuleToAccount accept sdk.Coins. Using []sdk.Coin here causes friction and type mismatches elsewhere.

 type TestnetAccount struct {
   Address  sdk.AccAddress `json:"address"`
-  Balances []sdk.Coin     `json:"balances"`
+  Balances sdk.Coins      `json:"balances"`
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type TestnetAccount struct {
Address sdk.AccAddress `json:"address"`
Balances []sdk.Coin `json:"balances"`
}
type TestnetAccount struct {
Address sdk.AccAddress `json:"address"`
Balances sdk.Coins `json:"balances"`
}

Comment on lines +63 to 64
Accounts []akash.TestnetAccount `json:"accounts"`
Gov akash.TestnetGovConfig `json:"gov"`
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Bech32 JSON parsing gap for Accounts/Delegations (sdk.AccAddress).

cfg.Accounts uses app.TestnetAccount, which has sdk.AccAddress. Without a custom UnmarshalJSON, JSON expects base64, not bech32. Same for Delegations’ Address field. This will confuse users and likely break config loading.

Two viable fixes (pick one):

  • Implement UnmarshalJSON on app.TestnetAccount and app.TestnetDelegation to parse bech32 addresses, or
  • Keep local testnetify JSON types that use your AccAddress/ValAddress wrappers, then convert to app types before building appConfig.

I can draft the UnmarshalJSON implementations in app/testnet.go if you prefer. Would you like that?

🤖 Prompt for AI Agents
In cmd/akash/cmd/testnetify/config.go around lines 63-64, cfg.Accounts and
related Delegations use app.TestnetAccount/TestnetDelegation which contain
sdk.AccAddress/sdk.ValAddress that JSON unmarshals as base64 by default; update
to support bech32 by either (A) adding UnmarshalJSON methods on
app.TestnetAccount and app.TestnetDelegation to accept bech32 strings and decode
them into AccAddress/ValAddress during JSON unmarshal, or (B) create local
testnetify JSON DTOs that use lightweight bech32 string wrappers (or
AccAddress/ValAddress wrapper types with custom UnmarshalJSON) to parse bech32,
then convert those DTOs into the app types before building appConfig — implement
one approach consistently for both Accounts and Delegations and add tests for
bech32 parsing and error cases.

@troian troian merged commit 9a939d5 into main Oct 25, 2025
34 checks passed
@troian troian deleted the testnetify branch October 25, 2025 14:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant