Skip to content

[Bug] Issue-contract write commands ignore configured wallet/hotkey outside issues register #1424

@jakearmstrong59

Description

@jakearmstrong59

Summary

gitt config set wallet ... and gitt config set hotkey ... write canonical config keys to ~/.gittensor/config.json, and gitt issues register already honors those values when wallet flags are omitted.

Other signed issue-contract write commands do not. gitt vote *, gitt admin *, and gitt harvest pass their raw Click defaults into bt.Wallet(...), so a user with a configured wallet/hotkey can still sign with the wrong key, or fail because the command fallback wallet does not exist.

This is the wallet/hotkey member of the same CLI config-priority family already fixed for adjacent config keys in #1035, #1200, and #1364.

Affected Commands

Shared _make_contract_client(...) path:

  • gitt vote solution
  • gitt vote cancel
  • gitt admin cancel-issue
  • gitt admin payout-issue
  • gitt admin set-owner
  • gitt admin set-treasury
  • gitt admin add-vali
  • gitt admin remove-vali

Inline wallet construction path:

  • gitt harvest

Why This Happens

gitt issues register resolves wallet config explicitly:

effective_wallet = wallet_name if wallet_name != 'default' else config.get('wallet', wallet_name)
effective_hotkey = wallet_hotkey if wallet_hotkey != 'default' else config.get('hotkey', wallet_hotkey)

But _make_contract_client(...) creates the wallet from the raw Click values:

wallet = bt.Wallet(name=wallet_name, hotkey=wallet_hotkey)

So vote/admin commands invoked without wallet flags use default/default, even when config contains a different wallet/hotkey.

gitt harvest has the same omission inline:

wallet = bt.Wallet(name=wallet_name, hotkey=wallet_hotkey)

Its command defaults are validator/default, so configured wallet values are also ignored there.

Reproduction

Create a config file:

{
  "wallet": "configured-wallet",
  "hotkey": "configured-hotkey"
}

Run a vote/admin command without wallet flags:

gitt vote cancel 1 "duplicate" --yes --contract <CONTRACT> --network test

Observed from a mocked CLI run capturing _make_contract_client(...) arguments:

("default", "default")

Expected:

("configured-wallet", "configured-hotkey")

For gitt harvest, the observed wallet values are:

("validator", "default")

instead of the configured wallet/hotkey.

Expected Behavior

All signed issue-contract write commands should follow the same wallet resolution order:

  1. Explicit CLI wallet flags win.
  2. ~/.gittensor/config.json wallet / hotkey are used when the CLI flags are omitted.
  3. Existing command defaults are used only when neither CLI nor config provides a value.

That preserves:

  • default/default as the final fallback for vote/admin commands.
  • validator/default as the final fallback for gitt harvest.

Actual Behavior

Only gitt issues register honors configured wallet / hotkey.

Vote/admin commands sign with default/default.

gitt harvest signs with validator/default.

This silently bypasses the configured signing key for irreversible on-chain actions.

Proposed Fix

Add a small shared wallet-resolution helper that can distinguish an omitted Click option from an explicit CLI value. This matters because gitt harvest uses validator/default as its command fallback, so checking only wallet_name != "default" is not enough.

Implementation shape:

from click.core import ParameterSource

def resolve_wallet_config(
    wallet_name: str,
    wallet_hotkey: str,
    *,
    wallet_default: str = "default",
    hotkey_default: str = "default",
) -> tuple[str, str]:
    ctx = click.get_current_context(silent=True)
    config = load_config()

    if ctx is None:
        wallet_explicit = wallet_name != wallet_default
        hotkey_explicit = wallet_hotkey != hotkey_default
    else:
        wallet_explicit = ctx.get_parameter_source("wallet_name") == ParameterSource.COMMANDLINE
        hotkey_explicit = ctx.get_parameter_source("wallet_hotkey") == ParameterSource.COMMANDLINE

    effective_wallet = wallet_name if wallet_explicit else config.get("wallet", wallet_default)
    effective_hotkey = wallet_hotkey if hotkey_explicit else config.get("hotkey", hotkey_default)
    return effective_wallet, effective_hotkey

Use it in _make_contract_client(...) with vote/admin defaults:

effective_wallet, effective_hotkey = resolve_wallet_config(
    wallet_name,
    wallet_hotkey,
    wallet_default="default",
    hotkey_default="default",
)
wallet = bt.Wallet(name=effective_wallet, hotkey=effective_hotkey)

Use it in gitt harvest with harvest's existing fallback:

effective_wallet, effective_hotkey = resolve_wallet_config(
    wallet_name,
    wallet_hotkey,
    wallet_default="validator",
    hotkey_default="default",
)
wallet = bt.Wallet(name=effective_wallet, hotkey=effective_hotkey)

Suggested Regression Tests

  • vote/admin commands without wallet flags use configured wallet / hotkey
  • vote/admin explicit wallet flags still win
  • harvest without wallet flags uses configured wallet / hotkey
  • harvest without config preserves the old validator/default fallback
  • explicit --wallet default --hotkey default still wins over config

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions