Skip to content
Merged
54 changes: 53 additions & 1 deletion chia/_tests/cmds/test_farm_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,15 @@ async def receiver_available() -> bool:
wallet_rpc_port = wallet_service.rpc_server.webserver.listen_port
farmer_rpc_port = farmer_service.rpc_server.webserver.listen_port

await summary(full_node_rpc_port, wallet_rpc_port, None, farmer_rpc_port, bt.root_path)
# Test with include_pool_rewards=False (original test)
await summary(
rpc_port=full_node_rpc_port,
wallet_rpc_port=wallet_rpc_port,
harvester_rpc_port=None,
farmer_rpc_port=farmer_rpc_port,
include_pool_rewards=False,
root_path=bt.root_path,
)

captured = capsys.readouterr()
match = re.search(r"^.+(Farming status:.+)$", captured.out, re.DOTALL)
Expand All @@ -64,3 +72,47 @@ async def receiver_available() -> bool:
assert "e (effective)" in lines[8]
assert "Estimated network space:" in lines[9]
assert "Expected time to win:" in lines[10]

# Test with include_pool_rewards=True
await summary(
rpc_port=full_node_rpc_port,
wallet_rpc_port=wallet_rpc_port,
harvester_rpc_port=None,
farmer_rpc_port=farmer_rpc_port,
include_pool_rewards=True,
root_path=bt.root_path,
)

captured = capsys.readouterr()
match = re.search(r"Farming status:.*", captured.out, re.DOTALL)
assert match, "no 'Farming status:' line"
output = match.group(0).strip()
lines = [line.strip() for line in output.splitlines()]

# always check these first six lines
assert lines[0].startswith("Farming status:")
assert lines[1].startswith("Total chia farmed:")
assert lines[2].startswith("User transaction fees:")
assert lines[3].startswith("Farmer rewards:")
assert lines[4].startswith("Pool rewards:")
assert lines[5].startswith("Total rewards:")

# decide where the harvester section starts
if "Current/Last height farmed:" in output:
# we saw the height-farmed block, so it occupies lines[6-8]
assert lines[6].startswith("Current/Last height farmed:")
assert lines[7].startswith("Blocks since last farmed:")
assert lines[8].startswith("Time since last farmed:")
harvester_idx = 9
else:
# no height block, so harvester begins at line 6
harvester_idx = 6

# now the harvester lines
assert lines[harvester_idx] == "Local Harvester"
assert "plots of size" in lines[harvester_idx + 1]
assert lines[harvester_idx + 2].startswith("Plot count for all harvesters:")
assert lines[harvester_idx + 3].startswith("Total size of plots:")
assert lines[harvester_idx + 4].startswith("Estimated network space:")
assert lines[harvester_idx + 5].startswith("Expected time to win:")
assert lines[harvester_idx + 6].startswith("Note:")
9 changes: 9 additions & 0 deletions chia/cmds/farm.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,21 @@ def farm_cmd() -> None:
default=None,
show_default=True,
)
@click.option(
"-i",
"--include-pool-rewards",
help="Include pool farming rewards in the total farmed amount",
is_flag=True,
default=False,
)
@click.pass_context
def summary_cmd(
ctx: click.Context,
rpc_port: Optional[int],
wallet_rpc_port: Optional[int],
harvester_rpc_port: Optional[int],
farmer_rpc_port: Optional[int],
include_pool_rewards: bool,
) -> None:
import asyncio

Expand All @@ -67,6 +75,7 @@ def summary_cmd(
wallet_rpc_port,
harvester_rpc_port,
farmer_rpc_port,
include_pool_rewards,
root_path=ChiaCliContext.set_default(ctx).root_path,
)
)
Expand Down
28 changes: 23 additions & 5 deletions chia/cmds/farm_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,13 @@ async def get_average_block_time(rpc_port: Optional[int], root_path: Path) -> fl
return (curr.timestamp - past_curr.timestamp) / (curr.height - past_curr.height)


async def get_wallets_stats(wallet_rpc_port: Optional[int], root_path: Path) -> Optional[dict[str, Any]]:
async def get_wallets_stats(
wallet_rpc_port: Optional[int],
root_path: Path,
include_pool_rewards: bool,
) -> Optional[dict[str, Any]]:
async with get_any_service_client(WalletRpcClient, root_path, wallet_rpc_port) as (wallet_client, _):
return await wallet_client.get_farmed_amount()
return await wallet_client.get_farmed_amount(include_pool_rewards)


async def get_challenges(root_path: Path, farmer_rpc_port: Optional[int]) -> Optional[list[dict[str, Any]]]:
Expand Down Expand Up @@ -80,6 +84,7 @@ async def summary(
wallet_rpc_port: Optional[int],
harvester_rpc_port: Optional[int],
farmer_rpc_port: Optional[int],
include_pool_rewards: bool,
root_path: Path,
) -> None:
harvesters_summary = await get_harvesters_summary(farmer_rpc_port, root_path)
Expand All @@ -97,7 +102,7 @@ async def summary(
wallet_not_ready: bool = False
amounts = None
try:
amounts = await get_wallets_stats(wallet_rpc_port, root_path)
amounts = await get_wallets_stats(wallet_rpc_port, root_path, include_pool_rewards)
except CliRpcConnectionError:
wallet_not_ready = True
except Exception:
Expand All @@ -120,8 +125,21 @@ async def summary(
if amounts is not None:
print(f"Total chia farmed: {amounts['farmed_amount'] / units['chia']}")
print(f"User transaction fees: {amounts['fee_amount'] / units['chia']}")
print(f"Block rewards: {(amounts['farmer_reward_amount'] + amounts['pool_reward_amount']) / units['chia']}")
print(f"Last height farmed: {amounts['last_height_farmed']}")
if include_pool_rewards:
print(f"Farmer rewards: {amounts['farmer_reward_amount'] / units['chia']}")
print(f"Pool rewards: {amounts['pool_reward_amount'] / units['chia']}")
print(f"Total rewards: {(amounts['farmer_reward_amount'] + amounts['pool_reward_amount']) / units['chia']}")
if blockchain_state is not None and blockchain_state["peak"] is not None:
peak_height = blockchain_state["peak"].height
blocks_since_last_farm = peak_height - amounts["last_height_farmed"]
print(f"Current/Last height farmed: {peak_height}/{amounts['last_height_farmed']}")
print(f"Blocks since last farmed: {blocks_since_last_farm}")
print(
f"Time since last farmed: {format_minutes(int((blocks_since_last_farm * SECONDS_PER_BLOCK) / 60))}"
)
else:
print(f"Block rewards: {(amounts['farmer_reward_amount'] + amounts['pool_reward_amount']) / units['chia']}")
print(f"Last height farmed: {amounts['last_height_farmed']}")

class PlotStats:
total_plot_size = 0
Expand Down
10 changes: 8 additions & 2 deletions chia/wallet/wallet_rpc_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3664,12 +3664,18 @@ async def get_farmed_amount(self, request: dict[str, Any]) -> EndpointResult:
fee_amount = 0
blocks_won = 0
last_height_farmed = uint32(0)

include_pool_rewards = request.get("include_pool_rewards", False)

for record in tx_records:
if record.wallet_id not in self.service.wallet_state_manager.wallets:
continue
if record.type == TransactionType.COINBASE_REWARD.value:
if self.service.wallet_state_manager.wallets[record.wallet_id].type() == WalletType.POOLING_WALLET:
# Don't add pool rewards for pool wallets.
if (
not include_pool_rewards
and self.service.wallet_state_manager.wallets[record.wallet_id].type() == WalletType.POOLING_WALLET
):
# Don't add pool rewards for pool wallets unless explicitly requested
continue
pool_reward_amount += record.amount
height = record.height_farmed(self.service.constants.GENESIS_CHALLENGE)
Expand Down
4 changes: 2 additions & 2 deletions chia/wallet/wallet_rpc_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,8 @@ async def extend_derivation_index(self, index: int) -> str:
updated_index = response["index"]
return str(updated_index)

async def get_farmed_amount(self) -> dict[str, Any]:
return await self.fetch("get_farmed_amount", {})
async def get_farmed_amount(self, include_pool_rewards: bool = False) -> dict[str, Any]:
return await self.fetch("get_farmed_amount", {"include_pool_rewards": include_pool_rewards})

async def create_signed_transactions(
self,
Expand Down
Loading