mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2026-08-24 10:05:29 -05:00
67cdfcda41
* build(deps): bump ruff from 0.15.21 to 0.16.0 Bumps [ruff](https://github.com/astral-sh/ruff) from 0.15.21 to 0.16.0. - [Release notes](https://github.com/astral-sh/ruff/releases) - [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md) - [Commits](https://github.com/astral-sh/ruff/compare/0.15.21...0.16.0) --- updated-dependencies: - dependency-name: ruff dependency-version: 0.16.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * affect changes * Restrict formtting to chia/tools/benchmarks * Fix generated protocol files * more noqa * network protocol files --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matt <quexington@gmail.com>
644 lines
20 KiB
Python
644 lines
20 KiB
Python
from __future__ import annotations
|
|
|
|
import pathlib
|
|
import textwrap
|
|
from collections.abc import Sequence
|
|
from dataclasses import asdict
|
|
from decimal import Decimal
|
|
from typing import Any
|
|
|
|
import click
|
|
import pytest
|
|
from chia_rs.sized_bytes import bytes32
|
|
from chia_rs.sized_ints import uint64
|
|
from click.testing import CliRunner
|
|
|
|
from chia._tests.environments.wallet import STANDARD_TX_ENDPOINT_ARGS, WalletTestFramework
|
|
from chia._tests.wallet.conftest import * # ruff: ignore[undefined-local-with-import-star]
|
|
from chia.cmds.cmd_classes import ChiaCliContext, ChiaCommand, chia_command, option
|
|
from chia.cmds.cmd_helpers import (
|
|
_TRANSACTION_ENDPOINT_DECORATOR_APPLIED,
|
|
NeedsCoinSelectionConfig,
|
|
NeedsTXConfig,
|
|
NeedsWalletRPC,
|
|
TransactionEndpoint,
|
|
TransactionEndpointWithTimelocks,
|
|
transaction_endpoint_runner,
|
|
)
|
|
from chia.cmds.cmds_util import coin_selection_args, tx_config_args, tx_out_cmd
|
|
from chia.cmds.param_types import CliAmount
|
|
from chia.wallet.conditions import ConditionValidTimes
|
|
from chia.wallet.transaction_record import TransactionRecord
|
|
from chia.wallet.util.tx_config import CoinSelectionConfig, TXConfig
|
|
|
|
|
|
def check_click_parsing(cmd: ChiaCommand, *args: str, context: ChiaCliContext | None = None) -> None:
|
|
"""
|
|
Helper function to test that the framework correctly parses a commandline string to a command object.
|
|
|
|
The first argument is the expected result of parsing, and the rest of the arguments are strings that would
|
|
be passed to the commandline.
|
|
"""
|
|
|
|
@click.group()
|
|
def _cmd() -> None:
|
|
pass
|
|
|
|
mock_type = type(cmd.__class__.__name__, (cmd.__class__,), {})
|
|
|
|
def dict_compare_with_ignore_context(one: dict[str, Any], two: dict[str, Any]) -> None:
|
|
for k, v in one.items():
|
|
if k == "context":
|
|
continue
|
|
elif isinstance(v, dict):
|
|
dict_compare_with_ignore_context(v, two[k])
|
|
else:
|
|
assert v == two[k]
|
|
|
|
def new_run(self: Any) -> None:
|
|
# cmd is appropriately not recognized as a dataclass but I'm not sure how to hint that something is a dataclass
|
|
dict_compare_with_ignore_context(asdict(cmd), asdict(self)) # type: ignore[call-overload]
|
|
|
|
# We hack this in because more robust solutions are harder and probably not worth it
|
|
setattr(new_run, _TRANSACTION_ENDPOINT_DECORATOR_APPLIED, True)
|
|
|
|
setattr(mock_type, "run", new_run)
|
|
chia_command(group=_cmd, name="_", short_help="", help="")(mock_type)
|
|
|
|
if context is None:
|
|
context = ChiaCliContext()
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(_cmd, ["_", *args], catch_exceptions=False, obj=context.to_click())
|
|
assert result.output == ""
|
|
|
|
|
|
def test_cmd_bases() -> None:
|
|
@click.group()
|
|
def cmd() -> None:
|
|
pass
|
|
|
|
@chia_command(group=cmd, name="temp_cmd", short_help="blah", help="n/a")
|
|
class TempCMD:
|
|
def run(self) -> None:
|
|
print("syncronous")
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_async", short_help="blah", help="n/a")
|
|
class TempCMDAsync:
|
|
async def run(self) -> None:
|
|
print("asyncronous")
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(
|
|
cmd,
|
|
["--help"],
|
|
catch_exceptions=False,
|
|
)
|
|
assert result.output == textwrap.dedent(
|
|
"""\
|
|
Usage: cmd [OPTIONS] COMMAND [ARGS]...
|
|
|
|
Options:
|
|
--help Show this message and exit.
|
|
|
|
Commands:
|
|
temp_cmd blah
|
|
temp_cmd_async blah
|
|
"""
|
|
)
|
|
result = runner.invoke(
|
|
cmd,
|
|
["temp_cmd"],
|
|
catch_exceptions=False,
|
|
)
|
|
assert result.output == "syncronous\n"
|
|
result = runner.invoke(
|
|
cmd,
|
|
["temp_cmd_async"],
|
|
catch_exceptions=False,
|
|
)
|
|
assert result.output == "asyncronous\n"
|
|
|
|
|
|
def test_option_loading() -> None:
|
|
@click.group()
|
|
def cmd() -> None:
|
|
pass
|
|
|
|
@chia_command(group=cmd, name="temp_cmd", short_help="blah", help="n/a")
|
|
class TempCMD:
|
|
some_option: int = option("-o", "--some-option", required=True, type=int)
|
|
choices: list[str] = option("--choice", multiple=True, type=str)
|
|
|
|
def run(self) -> None:
|
|
print(self.some_option)
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_2", short_help="blah", help="n/a")
|
|
class TempCMD2:
|
|
some_option: int = option("-o", "--some-option", required=True, type=int, default=13)
|
|
|
|
def run(self) -> None:
|
|
print(self.some_option)
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(
|
|
cmd,
|
|
["temp_cmd"],
|
|
catch_exceptions=False,
|
|
)
|
|
assert "Missing option '-o' / '--some-option'" in result.output
|
|
result = runner.invoke(
|
|
cmd,
|
|
[
|
|
"temp_cmd",
|
|
"-o",
|
|
"13",
|
|
],
|
|
catch_exceptions=False,
|
|
)
|
|
assert "13\n" == result.output
|
|
result = runner.invoke(
|
|
cmd,
|
|
[
|
|
"temp_cmd_2",
|
|
],
|
|
catch_exceptions=False,
|
|
)
|
|
assert "13\n" == result.output
|
|
|
|
assert TempCMD2() == TempCMD2(some_option=13)
|
|
|
|
|
|
def test_context_requirement() -> None:
|
|
@click.group()
|
|
@click.pass_context
|
|
def cmd(ctx: click.Context) -> None:
|
|
ctx.obj = ChiaCliContext(root_path=pathlib.Path("foo", "bar")).to_click()
|
|
|
|
@chia_command(group=cmd, name="temp_cmd", short_help="blah", help="n/a")
|
|
class TempCMD:
|
|
context: ChiaCliContext
|
|
|
|
def run(self) -> None:
|
|
assert self.context.root_path == pathlib.Path("foo", "bar")
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(
|
|
cmd,
|
|
["temp_cmd"],
|
|
catch_exceptions=False,
|
|
)
|
|
assert result.output == ""
|
|
|
|
# Test that other variables named context are disallowed
|
|
with pytest.raises(ValueError, match="context"):
|
|
|
|
@chia_command(group=cmd, name="shouldnt_work", short_help="blah", help="n/a")
|
|
class BadCMD:
|
|
context: int
|
|
|
|
def run(self) -> None: ...
|
|
|
|
|
|
def test_typing() -> None:
|
|
@click.group()
|
|
def cmd() -> None:
|
|
pass
|
|
|
|
@chia_command(group=cmd, name="temp_cmd", short_help="blah", help="n/a")
|
|
class TempCMD:
|
|
integer: int = option("--integer", default=1, required=False)
|
|
text: str = option("--text", default="1", required=False)
|
|
boolean: bool = option("--boolean", default=True, required=False)
|
|
floating_point: float = option("--floating-point", default=1.1, required=False)
|
|
blob: bytes = option("--blob", default=b"foo", required=False)
|
|
blob32: bytes32 = option("--blob32", default=bytes32([1] * 32), required=False)
|
|
choice: str = option("--choice", default="a", type=click.Choice(["a", "b"]), required=False)
|
|
|
|
def run(self) -> None: ...
|
|
|
|
check_click_parsing(TempCMD())
|
|
check_click_parsing(
|
|
TempCMD(),
|
|
"--integer",
|
|
"1",
|
|
"--text",
|
|
"1",
|
|
"--boolean",
|
|
"true",
|
|
"--floating-point",
|
|
"1.1",
|
|
"--blob",
|
|
"0x666f6f",
|
|
"--blob32",
|
|
"0x0101010101010101010101010101010101010101010101010101010101010101",
|
|
"--choice",
|
|
"a",
|
|
)
|
|
|
|
# Test optional
|
|
@chia_command(group=cmd, name="temp_cmd_optional", short_help="blah", help="n/a")
|
|
class TempCMDOptional:
|
|
optional: int | None = option("--optional", required=False)
|
|
|
|
def run(self) -> None: ...
|
|
|
|
check_click_parsing(TempCMDOptional(optional=None))
|
|
check_click_parsing(TempCMDOptional(optional=1), "--optional", "1")
|
|
|
|
# Test optional failure
|
|
with pytest.raises(TypeError):
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_optional_bad", short_help="blah", help="n/a")
|
|
class TempCMDOptionalBad2:
|
|
optional: int | None = option("--optional", required=True)
|
|
|
|
def run(self) -> None: ...
|
|
|
|
with pytest.raises(TypeError):
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_optional_bad", short_help="blah", help="n/a")
|
|
class TempCMDOptionalBad3:
|
|
optional: int | None = option("--optional", default="string", required=False)
|
|
|
|
def run(self) -> None: ...
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_optional_fine", short_help="blah", help="n/a")
|
|
class TempCMDOptionalBad4:
|
|
optional: int | None = option("--optional", default=None, required=False)
|
|
|
|
def run(self) -> None: ...
|
|
|
|
# Test multiple
|
|
@chia_command(group=cmd, name="temp_cmd_sequence", short_help="blah", help="n/a")
|
|
class TempCMDSequence:
|
|
sequence: Sequence[int] = option("--sequence", multiple=True)
|
|
|
|
def run(self) -> None: ...
|
|
|
|
check_click_parsing(TempCMDSequence(sequence=tuple()))
|
|
check_click_parsing(TempCMDSequence(sequence=(1, 2)), "--sequence", "1", "--sequence", "2")
|
|
|
|
# Test sequence failure
|
|
with pytest.raises(TypeError):
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_sequence_bad", short_help="blah", help="n/a")
|
|
class TempCMDSequenceBad:
|
|
sequence: Sequence[int] = option("--sequence")
|
|
|
|
def run(self) -> None: ...
|
|
|
|
with pytest.raises(TypeError):
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_sequence_bad", short_help="blah", help="n/a")
|
|
class TempCMDSequenceBad2:
|
|
sequence: int = option("--sequence", multiple=True)
|
|
|
|
def run(self) -> None: ...
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_sequence_bad", short_help="blah", help="n/a")
|
|
class TempCMDSequenceBad3:
|
|
sequence: Sequence[int] = option("--sequence", default=[1, 2, 3], multiple=True)
|
|
|
|
def run(self) -> None: ...
|
|
|
|
with pytest.raises(TypeError):
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_sequence_bad", short_help="blah", help="n/a")
|
|
class TempCMDSequenceBad4:
|
|
sequence: Sequence[int] = option("--sequence", default=(1, 2, "3"), multiple=True)
|
|
|
|
def run(self) -> None: ...
|
|
|
|
# Test invalid type
|
|
with pytest.raises(TypeError):
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_bad_type", short_help="blah", help="n/a")
|
|
class TempCMDBadType:
|
|
sequence: list[int] = option("--sequence")
|
|
|
|
def run(self) -> None: ...
|
|
|
|
# Test invalid default
|
|
with pytest.raises(TypeError):
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_bad_default", short_help="blah", help="n/a")
|
|
class TempCMDBadDefault:
|
|
integer: int = option("--int", default="string")
|
|
|
|
def run(self) -> None: ...
|
|
|
|
# Test bytes parsing
|
|
@chia_command(group=cmd, name="temp_cmd_bad_bytes", short_help="blah", help="n/a")
|
|
class TempCMDBadBytes:
|
|
blob: bytes = option("--blob", required=True)
|
|
|
|
def run(self) -> None: ...
|
|
|
|
@chia_command(group=cmd, name="temp_cmd_bad_bytes32", short_help="blah", help="n/a")
|
|
class TempCMDBadBytes32:
|
|
blob32: bytes32 = option("--blob32", required=True)
|
|
|
|
def run(self) -> None: ...
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(
|
|
cmd,
|
|
["temp_cmd_bad_bytes", "--blob", "not a blob"],
|
|
catch_exceptions=False,
|
|
)
|
|
assert "not a valid hex string" in result.output
|
|
|
|
result = runner.invoke(
|
|
cmd,
|
|
["temp_cmd_bad_bytes32", "--blob32", "0xdeadbeef"],
|
|
catch_exceptions=False,
|
|
)
|
|
assert "not a valid 32-byte hex string" in result.output
|
|
|
|
|
|
@pytest.mark.limit_consensus_modes(reason="doesn't matter")
|
|
@pytest.mark.parametrize(
|
|
"wallet_environments",
|
|
[
|
|
{
|
|
"num_environments": 1,
|
|
"blocks_needed": [1],
|
|
"trusted": True,
|
|
"reuse_puzhash": False,
|
|
}
|
|
],
|
|
indirect=True,
|
|
)
|
|
@pytest.mark.anyio
|
|
async def test_wallet_rpc_helper(wallet_environments: WalletTestFramework) -> None:
|
|
port: int = wallet_environments.environments[0].rpc_client.port
|
|
|
|
assert wallet_environments.environments[0].node.logged_in_fingerprint is not None
|
|
fingerprint: int = wallet_environments.environments[0].node.logged_in_fingerprint
|
|
|
|
@click.group()
|
|
def cmd() -> None:
|
|
pass
|
|
|
|
@chia_command(group=cmd, name="temp_cmd", short_help="blah", help="n/a")
|
|
class TempCMD:
|
|
rpc_info: NeedsWalletRPC
|
|
|
|
def run(self) -> None:
|
|
pass
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(
|
|
cmd,
|
|
[
|
|
"temp_cmd",
|
|
"-wp",
|
|
str(port),
|
|
"-f",
|
|
str(fingerprint),
|
|
],
|
|
catch_exceptions=False,
|
|
)
|
|
assert result.output == ""
|
|
|
|
result = runner.invoke(
|
|
cmd,
|
|
[
|
|
"temp_cmd",
|
|
],
|
|
catch_exceptions=False,
|
|
)
|
|
assert result.output == ""
|
|
|
|
expected_command = TempCMD(
|
|
rpc_info=NeedsWalletRPC(
|
|
context=ChiaCliContext(root_path=wallet_environments.environments[0].node.root_path),
|
|
wallet_rpc_port=port,
|
|
fingerprint=fingerprint,
|
|
),
|
|
)
|
|
check_click_parsing(expected_command, "-wp", str(port), "-f", str(fingerprint))
|
|
|
|
async with expected_command.rpc_info.wallet_rpc(consume_errors=False) as client_info:
|
|
assert (await client_info.client.get_logged_in_fingerprint()).fingerprint == fingerprint
|
|
|
|
# We don't care about setting the correct arg type here
|
|
test_present_client_info = TempCMD(rpc_info=NeedsWalletRPC(client_info="hello world")) # type: ignore[arg-type]
|
|
async with test_present_client_info.rpc_info.wallet_rpc(consume_errors=False) as client_info:
|
|
assert client_info == "hello world" # type: ignore[comparison-overlap]
|
|
|
|
|
|
def test_tx_config_helper() -> None:
|
|
@click.group()
|
|
def cmd() -> None:
|
|
pass # pragma: no cover
|
|
|
|
@chia_command(group=cmd, name="cs_cmd", short_help="blah", help="blah")
|
|
class CsCMD:
|
|
coin_selection_loader: NeedsCoinSelectionConfig
|
|
|
|
def run(self) -> None:
|
|
# ignoring the `None` return here for convenient testing sake
|
|
return self.coin_selection_loader.load_coin_selection_config(100) # type: ignore[return-value]
|
|
|
|
example_cs_cmd = CsCMD(
|
|
coin_selection_loader=NeedsCoinSelectionConfig(
|
|
min_coin_amount=CliAmount(amount=Decimal("0.01"), mojos=False),
|
|
max_coin_amount=CliAmount(amount=Decimal("0.01"), mojos=False),
|
|
amounts_to_exclude=(CliAmount(amount=Decimal("0.01"), mojos=False),),
|
|
coins_to_exclude=(bytes32([0] * 32),),
|
|
coins_to_include=(bytes32([1] * 32),),
|
|
primary_coin=bytes32([1] * 32),
|
|
)
|
|
)
|
|
|
|
check_click_parsing(
|
|
example_cs_cmd,
|
|
"--min-coin-amount",
|
|
"0.01",
|
|
"--max-coin-amount",
|
|
"0.01",
|
|
"--exclude-amount",
|
|
"0.01",
|
|
"--exclude-coin",
|
|
bytes32([0] * 32).hex(),
|
|
"--include-coin",
|
|
bytes32([1] * 32).hex(),
|
|
"--primary-coin",
|
|
bytes32([1] * 32).hex(),
|
|
)
|
|
|
|
# again, convenience for testing sake
|
|
assert example_cs_cmd.run() == CoinSelectionConfig( # type: ignore[func-returns-value]
|
|
min_coin_amount=uint64(1),
|
|
max_coin_amount=uint64(1),
|
|
excluded_coin_amounts=[uint64(1)],
|
|
excluded_coin_ids=[bytes32([0] * 32)],
|
|
included_coin_ids=[bytes32([1] * 32)],
|
|
primary_coin=bytes32([1] * 32),
|
|
)
|
|
|
|
@chia_command(group=cmd, name="tx_config_cmd", short_help="blah", help="blah")
|
|
class TXConfigCMD:
|
|
tx_config_loader: NeedsTXConfig
|
|
|
|
def run(self) -> None:
|
|
# ignoring the `None` return here for convenient testing sake
|
|
return self.tx_config_loader.load_tx_config(100, {}, 0) # type: ignore[return-value]
|
|
|
|
example_tx_config_cmd = TXConfigCMD(
|
|
tx_config_loader=NeedsTXConfig(
|
|
min_coin_amount=CliAmount(amount=Decimal("0.01"), mojos=False),
|
|
max_coin_amount=CliAmount(amount=Decimal("0.01"), mojos=False),
|
|
amounts_to_exclude=(CliAmount(amount=Decimal("0.01"), mojos=False),),
|
|
coins_to_exclude=(bytes32([0] * 32),),
|
|
coins_to_include=(bytes32([1] * 32),),
|
|
primary_coin=bytes32([1] * 32),
|
|
reuse=False,
|
|
)
|
|
)
|
|
|
|
check_click_parsing(
|
|
example_tx_config_cmd,
|
|
"--min-coin-amount",
|
|
"0.01",
|
|
"--max-coin-amount",
|
|
"0.01",
|
|
"--exclude-amount",
|
|
"0.01",
|
|
"--exclude-coin",
|
|
bytes32([0] * 32).hex(),
|
|
"--include-coin",
|
|
bytes32([1] * 32).hex(),
|
|
"--primary-coin",
|
|
bytes32([1] * 32).hex(),
|
|
"--new-address",
|
|
)
|
|
|
|
# again, convenience for testing sake
|
|
assert example_tx_config_cmd.run() == TXConfig( # type: ignore[func-returns-value]
|
|
min_coin_amount=uint64(1),
|
|
max_coin_amount=uint64(1),
|
|
excluded_coin_amounts=[uint64(1)],
|
|
excluded_coin_ids=[bytes32([0] * 32)],
|
|
included_coin_ids=[bytes32([1] * 32)],
|
|
primary_coin=bytes32([1] * 32),
|
|
reuse_puzhash=False,
|
|
)
|
|
|
|
|
|
@pytest.mark.anyio
|
|
async def test_transaction_endpoint_mixin() -> None:
|
|
@click.group()
|
|
def cmd() -> None:
|
|
pass # pragma: no cover
|
|
|
|
@chia_command(group=cmd, name="bad_cmd", short_help="blah", help="blah")
|
|
class BadCMD(TransactionEndpoint):
|
|
def run(self) -> None: # type: ignore[override]
|
|
pass # pragma: no cover
|
|
|
|
with pytest.raises(TypeError, match="transaction_endpoint_runner"):
|
|
BadCMD(**STANDARD_TX_ENDPOINT_ARGS)
|
|
|
|
@chia_command(group=cmd, name="cs_cmd", short_help="blah", help="blah")
|
|
class TxCMD(TransactionEndpoint):
|
|
@transaction_endpoint_runner
|
|
async def run(self) -> list[TransactionRecord]:
|
|
assert self.load_condition_valid_times() == ConditionValidTimes(
|
|
min_time=uint64(10),
|
|
max_time=uint64(20),
|
|
)
|
|
return []
|
|
|
|
# Check that our default object lines up with the default options
|
|
check_click_parsing(TxCMD(**STANDARD_TX_ENDPOINT_ARGS))
|
|
|
|
example_tx_cmd = TxCMD(
|
|
**{
|
|
**STANDARD_TX_ENDPOINT_ARGS,
|
|
**dict(
|
|
fee=uint64(1_000_000_000_000 / 100),
|
|
push=False,
|
|
valid_at=10,
|
|
expires_at=20,
|
|
),
|
|
}
|
|
)
|
|
check_click_parsing(
|
|
example_tx_cmd,
|
|
"--fee",
|
|
"0.01",
|
|
"--no-push",
|
|
"--valid-at",
|
|
"10",
|
|
"--expires-at",
|
|
"20",
|
|
)
|
|
|
|
await example_tx_cmd.run() # trigger inner assert
|
|
|
|
|
|
# While we sit in between two paradigms, this test is in place to ensure they remain in sync.
|
|
# Delete this if the old decorators are deleted.
|
|
def test_old_decorator_support() -> None:
|
|
@click.group()
|
|
def cmd() -> None:
|
|
pass # pragma: no cover
|
|
|
|
@chia_command(group=cmd, name="cs_cmd", short_help="blah", help="blah")
|
|
class CsCMD:
|
|
coin_selection_loader: NeedsCoinSelectionConfig
|
|
|
|
def run(self) -> None:
|
|
pass # pragma: no cover
|
|
|
|
@chia_command(group=cmd, name="tx_config_cmd", short_help="blah", help="blah")
|
|
class TXConfigCMD:
|
|
tx_config_loader: NeedsTXConfig
|
|
|
|
def run(self) -> None:
|
|
pass # pragma: no cover
|
|
|
|
@chia_command(group=cmd, name="tx_cmd", short_help="blah", help="blah")
|
|
class TxCMD(TransactionEndpoint):
|
|
@transaction_endpoint_runner
|
|
async def run(self) -> list[TransactionRecord]:
|
|
return [] # pragma: no cover
|
|
|
|
@chia_command(group=cmd, name="tx_w_tl_cmd", short_help="blah", help="blah")
|
|
class TxWTlCMD(TransactionEndpointWithTimelocks):
|
|
@transaction_endpoint_runner
|
|
async def run(self) -> list[TransactionRecord]:
|
|
return [] # pragma: no cover
|
|
|
|
@cmd.command("cs_cmd_dec")
|
|
@coin_selection_args
|
|
def cs_cmd(**kwargs: Any) -> None:
|
|
pass # pragma: no cover
|
|
|
|
@cmd.command("tx_config_cmd_dec")
|
|
@tx_config_args
|
|
def tx_config_cmd(**kwargs: Any) -> None:
|
|
pass # pragma: no cover
|
|
|
|
@cmd.command("tx_cmd_dec")
|
|
@tx_out_cmd(enable_timelock_args=False) # type: ignore[arg-type]
|
|
def tx_cmd(**kwargs: Any) -> None:
|
|
pass # pragma: no cover
|
|
|
|
@cmd.command("tx_w_tl_cmd_dec")
|
|
@tx_out_cmd(enable_timelock_args=True) # type: ignore[arg-type]
|
|
def tx_w_tl_cmd(**kwargs: Any) -> None:
|
|
pass # pragma: no cover
|
|
|
|
for command_name, command in cmd.commands.items():
|
|
if "_dec" in command_name:
|
|
continue
|
|
params = [param.to_info_dict() for param in cmd.commands[command_name].params]
|
|
for param in cmd.commands[f"{command_name}_dec"].params:
|
|
assert param.to_info_dict() in params
|