mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2024-09-19 14:48:38 +03:00
Fix chia wallet coins cli bugs (#14388)
* fix fee bug The fee should not be taken into account when dealing with CAT's or other non XCH coins. * fix broken CAT removals it was never implemented ... * Update wallet_rpc_api.py
This commit is contained in:
parent
69c7172152
commit
99fbb056e1
@ -13,6 +13,7 @@ from chia.types.coin_record import CoinRecord
|
||||
from chia.util.bech32m import decode_puzzle_hash, encode_puzzle_hash
|
||||
from chia.util.ints import uint64, uint128
|
||||
from chia.wallet.transaction_record import TransactionRecord
|
||||
from chia.wallet.util.wallet_types import WalletType
|
||||
|
||||
|
||||
async def async_list(args: Dict[str, Any], wallet_client: WalletRpcClient, fingerprint: int) -> None:
|
||||
@ -125,13 +126,14 @@ async def async_combine(args: Dict[str, Any], wallet_client: WalletRpcClient, fi
|
||||
if not await wallet_client.get_synced():
|
||||
print("Wallet not synced. Please wait.")
|
||||
return
|
||||
is_xch: bool = wallet_type == WalletType.STANDARD_WALLET # this lets us know if we are directly combining Chia
|
||||
final_max_amount = uint64(int(max_amount * mojo_per_unit)) if not target_coin_ids else uint64(0)
|
||||
final_min_coin_amount: uint64 = uint64(int(min_coin_amount * mojo_per_unit))
|
||||
final_excluded_amounts: List[uint64] = [uint64(int(Decimal(amount) * mojo_per_unit)) for amount in excluded_amounts]
|
||||
final_target_coin_amount = uint64(int(target_coin_amount * mojo_per_unit))
|
||||
if final_target_coin_amount != 0: # if we have a set target, just use standard coin selection.
|
||||
removals: List[Coin] = await wallet_client.select_coins(
|
||||
amount=final_target_coin_amount + final_fee,
|
||||
amount=(final_target_coin_amount + final_fee) if is_xch else final_target_coin_amount,
|
||||
wallet_id=wallet_id,
|
||||
max_coin_amount=final_max_amount,
|
||||
min_coin_amount=final_min_coin_amount,
|
||||
@ -163,11 +165,11 @@ async def async_combine(args: Dict[str, Any], wallet_client: WalletRpcClient, fi
|
||||
if input("Would you like to Continue? (y/n): ") != "y":
|
||||
return
|
||||
total_amount: uint128 = uint128(sum(coin.amount for coin in removals))
|
||||
if total_amount - final_fee <= 0:
|
||||
if is_xch and total_amount - final_fee <= 0:
|
||||
print("Total amount is less than 0 after fee, exiting.")
|
||||
return
|
||||
target_ph: bytes32 = decode_puzzle_hash(await wallet_client.get_next_address(wallet_id, False))
|
||||
additions = [{"amount": total_amount - final_fee, "puzzle_hash": target_ph}]
|
||||
additions = [{"amount": (total_amount - final_fee) if is_xch else total_amount, "puzzle_hash": target_ph}]
|
||||
transaction: TransactionRecord = await wallet_client.send_transaction_multi(
|
||||
wallet_id, additions, removals, final_fee
|
||||
)
|
||||
@ -195,8 +197,11 @@ async def async_split(args: Dict[str, Any], wallet_client: WalletRpcClient, fing
|
||||
if not await wallet_client.get_synced():
|
||||
print("Wallet not synced. Please wait.")
|
||||
return
|
||||
is_xch: bool = wallet_type == WalletType.STANDARD_WALLET # this lets us know if we are directly spitting Chia
|
||||
final_amount_per_coin = uint64(int(amount_per_coin * mojo_per_unit))
|
||||
total_amount = (final_amount_per_coin * number_of_coins) + final_fee
|
||||
total_amount = final_amount_per_coin * number_of_coins
|
||||
if is_xch:
|
||||
total_amount += final_fee
|
||||
# get full coin record from name, and validate information about it.
|
||||
removal_coin_record: CoinRecord = (await wallet_client.get_coin_records_by_names([target_coin_id]))[0]
|
||||
if removal_coin_record.coin.amount < total_amount:
|
||||
|
@ -1375,6 +1375,9 @@ class WalletRpcApi:
|
||||
puzzle_hashes.append(decode_puzzle_hash(request["inner_address"]))
|
||||
if "memos" in request:
|
||||
memos.append([mem.encode("utf-8") for mem in request["memos"]])
|
||||
coins: Optional[Set[Coin]] = None
|
||||
if "coins" in request and len(request["coins"]) > 0:
|
||||
coins = set([Coin.from_json_dict(coin_json) for coin_json in request["coins"]])
|
||||
fee: uint64 = uint64(request.get("fee", 0))
|
||||
min_coin_amount: uint64 = uint64(request.get("min_coin_amount", 0))
|
||||
max_coin_amount: uint64 = uint64(request.get("max_coin_amount", 0))
|
||||
@ -1385,7 +1388,7 @@ class WalletRpcApi:
|
||||
exclude_coin_amounts = [uint64(a) for a in exclude_coin_amounts]
|
||||
exclude_coin_ids: Optional[List] = request.get("exclude_coin_ids")
|
||||
if exclude_coin_ids is not None:
|
||||
exclude_coins: Set[Coin] = {
|
||||
exclude_coins: Optional[Set[Coin]] = {
|
||||
wr.coin
|
||||
for wr in await self.service.wallet_state_manager.coin_store.get_coin_records(
|
||||
[bytes32.from_hexstr(hex_id) for hex_id in exclude_coin_ids]
|
||||
@ -1393,13 +1396,14 @@ class WalletRpcApi:
|
||||
if wr is not None
|
||||
}
|
||||
else:
|
||||
exclude_coins = set()
|
||||
exclude_coins = None
|
||||
if hold_lock:
|
||||
async with self.service.wallet_state_manager.lock:
|
||||
txs: List[TransactionRecord] = await wallet.generate_signed_transaction(
|
||||
amounts,
|
||||
puzzle_hashes,
|
||||
fee,
|
||||
coins=coins,
|
||||
memos=memos if memos else None,
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
@ -1413,6 +1417,7 @@ class WalletRpcApi:
|
||||
amounts,
|
||||
puzzle_hashes,
|
||||
fee,
|
||||
coins=coins,
|
||||
memos=memos if memos else None,
|
||||
min_coin_amount=min_coin_amount,
|
||||
max_coin_amount=max_coin_amount,
|
||||
|
@ -635,6 +635,7 @@ class WalletRpcClient(RpcClient):
|
||||
exclude_amounts: Optional[List[uint64]] = None,
|
||||
exclude_coin_ids: Optional[List[str]] = None,
|
||||
additions: Optional[List[Dict[str, Any]]] = None,
|
||||
removals: Optional[List[Coin]] = None,
|
||||
) -> TransactionRecord:
|
||||
send_dict: Dict[str, Any] = {
|
||||
"wallet_id": wallet_id,
|
||||
@ -657,6 +658,8 @@ class WalletRpcClient(RpcClient):
|
||||
send_dict["additions"] = additions_hex
|
||||
else:
|
||||
raise ValueError("Must specify either amount and inner_address or additions")
|
||||
if removals is not None and len(removals) > 0:
|
||||
send_dict["coins"] = [c.to_json_dict() for c in removals]
|
||||
res = await self.fetch("cat_spend", send_dict)
|
||||
return TransactionRecord.from_json_dict_convenience(res["transaction"])
|
||||
|
||||
|
@ -508,6 +508,7 @@ async def test_send_transaction_multi(wallet_rpc_environment: WalletRpcTestEnvir
|
||||
|
||||
generated_funds = await generate_funds(full_node_api, env.wallet_1)
|
||||
|
||||
removals = await client.select_coins(1750000000000, wallet_id=1) # we want a coin that won't be selected by default
|
||||
outputs = await create_tx_outputs(wallet_2, [(uint64(1), ["memo_1"]), (uint64(2), ["memo_2"])])
|
||||
amount_outputs = sum(output["amount"] for output in outputs)
|
||||
amount_fee = uint64(amount_outputs + 1)
|
||||
@ -515,6 +516,7 @@ async def test_send_transaction_multi(wallet_rpc_environment: WalletRpcTestEnvir
|
||||
send_tx_res: TransactionRecord = await client.send_transaction_multi(
|
||||
1,
|
||||
outputs,
|
||||
coins=removals,
|
||||
fee=amount_fee,
|
||||
)
|
||||
spend_bundle = send_tx_res.spend_bundle
|
||||
@ -522,6 +524,7 @@ async def test_send_transaction_multi(wallet_rpc_environment: WalletRpcTestEnvir
|
||||
assert send_tx_res is not None
|
||||
|
||||
assert_tx_amounts(send_tx_res, outputs, amount_fee=amount_fee, change_expected=True)
|
||||
assert send_tx_res.removals == removals
|
||||
|
||||
await farm_transaction(full_node_api, wallet_node, spend_bundle)
|
||||
|
||||
@ -709,6 +712,16 @@ async def test_cat_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment):
|
||||
assert uncurry_puzzle(spend_bundle.coin_spends[0].puzzle_reveal.to_program()).mod == CAT_MOD
|
||||
await farm_transaction(full_node_api, wallet_node, spend_bundle)
|
||||
|
||||
# Test CAT spend with a fee and pre-specified removals / coins
|
||||
removals = await client.select_coins(amount=uint64(2), wallet_id=cat_0_id)
|
||||
tx_res = await client.cat_spend(cat_0_id, uint64(1), addr_1, uint64(5_000_000), ["the cat memo"], removals=removals)
|
||||
assert tx_res.wallet_id == cat_0_id
|
||||
spend_bundle = tx_res.spend_bundle
|
||||
assert spend_bundle is not None
|
||||
assert removals[0] in tx_res.removals
|
||||
assert uncurry_puzzle(spend_bundle.coin_spends[0].puzzle_reveal.to_program()).mod == CAT_MOD
|
||||
await farm_transaction(full_node_api, wallet_node, spend_bundle)
|
||||
|
||||
# Test unacknowledged CAT
|
||||
await wallet_node.wallet_state_manager.interested_store.add_unacknowledged_token(
|
||||
asset_id, "Unknown", uint32(10000), bytes32(b"\00" * 32)
|
||||
@ -716,8 +729,8 @@ async def test_cat_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment):
|
||||
cats = await client.get_stray_cats()
|
||||
assert len(cats) == 1
|
||||
|
||||
await time_out_assert(20, get_confirmed_balance, 15, client, cat_0_id)
|
||||
await time_out_assert(20, get_confirmed_balance, 5, client_2, cat_1_id)
|
||||
await time_out_assert(20, get_confirmed_balance, 14, client, cat_0_id)
|
||||
await time_out_assert(20, get_confirmed_balance, 6, client_2, cat_1_id)
|
||||
|
||||
# Test CAT coin selection
|
||||
selected_coins = await client.select_coins(amount=1, wallet_id=cat_0_id)
|
||||
|
Loading…
Reference in New Issue
Block a user